ERC-1155 Controller

Polygon Contract Address

View on Polygonscan

Source Code

ERC1155Controller.sol

Overview

The ERC1155Controller implements all of the functionality needed to mint, burn, approve, and transfer the ERC1155 option tokens (e.g. bTokens and wTokens). It inherits from the Open Zeppelin ERC1155PresetMinterPauser contract, which implements functions for minting, burning, approving, and transferring tokens, either as a single token or multiple tokens as a batch.

Any contract wishing to transfer SIREN option tokens will need the ERC1155Controller contract address.

We chose to use the ERC1155 interface instead of the more popular ERC20 standard because it provides us a more gas efficient way to create option series. Rather than deploy a new ERC20 contract with every new Series we create, we add an additional id to the same ERC1155 contract. It also standardizes the ERC1155.setApprovalForAll, which allows an owner address to make only a single onchain transaction in order to approve an operator account to transfer any/all of the option tokens, which is more gas efficient than an onchain transaction for each option token.

Functions

Modifiers

onlySeriesController

modifier onlySeriesController() {
require(
msg.sender == controller,
"ERC1155Controller: Sender must be the seriesController"
);
_;
}

Certain functions can only be called by the associated SeriesController contract, such as the mint and burn functions. This is to ensure that no arbitrary address can inflate or deflate the supply of option tokens.

onlyOwner

modifier onlyOwner() {
require(
hasRole(DEFAULT_ADMIN_ROLE, msg.sender),
"ERC1155Controller: Caller is not the owner"
);
_;
}

Certain functions can only be called by the SIREN protocol owner multisig address. The functions updateImplementation and transferOwnership exist so that the owners can update the contracts in the event of a critical vulnerability that puts user's funds at risk.

View/Pure Functions

uri

function uri(
uint256 _id
) public view override returns (string memory)

This implementation returns the same URI for all token types. It relies on the token type ID substitution mechanism https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. Clients calling this function must replace the \{id\} substring with the actual token type ID.

Parameters

Name

Type

Description

_id

uint256

The ID of the ERC1155 token

balanceOf

function balanceOf(
address account,
uint256 id
) public view override returns (uint256)

Returns the account's balance on the ERC1155 token id. In the ERC1155 standard, a single contract tracks multiple tokens using different ID's. This is similar to the ERC20 standard's balanceOf function, but the caller must also specify the ERC1155 token id.

Parameters

Name

Type

Description

account

address

The address of the user who's ERC1155 balance you wish to fetch

id

uint256

The ERC1155 token id

balanceOfBatch

function balanceOfBatch(
address[] memory accounts,
uint256[] memory ids
) public view override returns (uint256[] memory)

Returns the balances of multiple accounts for multiple ERC1155 token ids. This is a more gas-efficient way to fetch multiple balances, compared to multiple calls to balanceOf. The length of the accounts array must equal the length of the ids array.

Parameters

Name

Type

Description

accounts

address[] memory

The addresses of the users who's ERC1155 balances you wish to fetch

ids

uint256[] memory

The ERC1155 token ids

isApprovedForAll

function isApprovedForAll(
address account,
address operator
) public view override returns (bool)

Returns true if the account has approved operator to transfer all of account's bTokens and wTokens on its behalf, and false if the operator is not approved to transfer any of account's ERC1155 tokens. The ERC1155 standard does not expose a function for approving individual ERC1155 token ids, but does expose setApprovalForAll for approving the transfer of all account's ERC1155 tokens.

Parameters

Name

Type

Description

account

address

The address which owns the tokens and has approved the operator

operator

address

The address which has been delegated controll of account's funds

Mutating Functions

setApprovalForAll

function setApprovalForAll(
address operator,
bool approved
) public override

If approved is true, allows the operator to transfer all of the caller's bTokens and wTokens on the caller's behalf. If false, the operator can no longer transfer tokens. This is similar to the ERC20's approve function, except in the ERC1155 standard you only need to call the approval function once and forever after the operator can transfer any amount of tokens. However, this is more dangerous than single token approvals, because the operator has control over all of the caller's balance of ERC1155 tokens.

Parameters

Name

Type

Description

account

address

The address which owns the tokens and is approving/disapproving the operator to be able to transfer tokens

approved

bool

true if the account is allowing the operator to transfer the account's tokens, and false if the operator is already approved and account no longer wants operator to be approved to transfer its tokens

safeTransferFrom

function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public override

Transfers amount tokens of token type id from from to to. to cannot be the zero address, and if the caller is not from then prior to calling this function the from address must have called setApprovalForAll with the caller as the operator argument, or else this call will fail. If to refers to a smart contract, it must implement 'onERC1155Received'.

Parameters

Name

Type

Description

from

address

The address from which ERC1155 tokens will be transferred out of

to

address

The address into which the ERC1155 tokens will be transferred into

id

uint256

The identifier of the option token. Can be obtained by either SeriesController.bTokenIndex(_seriesId) or SeriesController.wTokenIndex(_seriesId)

amount

uint256

The amount of option token to transfer, in base units. The decimals will always be the same as the Series' underlying token'

data

bytes memory

Arbitrary data to be used by the individual ERC1155 token. For the SIREN protocol this can always unused, so it can be an empty array

safeTransferFromBatch

function safeTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public override

Similar to safeTransferFrom, but more gas efficient when multiple transactions for different amounts of different token ids must be sent to the same to address. Use this function rather than safeTransferFrom when the caller wants to save gas while sending multiple tokens to the same recipient address.

Parameters

Name

Type

Description

from

address

The address from which ERC1155 tokens will be transferred out of

to

address

The address into which the ERC1155 tokens will be transferred into

ids

uint256[] memory

The identifiers of the option token. Can be obtained by either SeriesController.bTokenIndex(_seriesId) or SeriesController.wTokenIndex(_seriesId)

amounts

uint256[] memory

The amounts of option token to transfer, in base units. The decimals will always be the same as the Series' underlying token'

data

bytes memory

Arbitrary data to be used by the individual ERC1155 token. For the SIREN protocol this can always unused, so it can be an empty array

mint

function mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) override(ERC1155PresetMinterPauserUpgradeable, IERC1155Controller)
onlySeriesController

Creates amount tokens of token type id and sends them to address to. to cannot be the zero address, and if to refers to a smart contract, it must implement 'onERC1155Received'.

Parameters

Name

Type

Description

to

address

The address into which the newly minted ERC1155 tokens will be transferred into

id

uint256

The identifier of the option token. Can be obtained by either SeriesController.bTokenIndex(_seriesId) or SeriesController.wTokenIndex(_seriesId)

amount

uint256

The amount of option token to mint, in base units. The decimals will always be the same as the Series' underlying token'

data

bytes memory

Arbitrary data to be used by the individual ERC1155 token. For the SIREN protocol this can always unused, so it can be an empty array

mintBatch

function mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
)
public
override(ERC1155PresetMinterPauserUpgradeable, IERC1155Controller)
onlySeriesController

Similar to mint, but more gas efficient when multiple transactions for different amounts of different token ids must be minted to the same to address. Use this function rather than mint when the caller wants to save gas while minting multiple tokens to the same recipient address.

The SeriesController calls this inside of SeriesController.mintOptions.

Parameters

Name

Type

Description

to

address

The address into which the newly minted ERC1155 tokens will be transferred into

ids

uint256[] memory

The identifiers of the option tokens. Can be obtained by either SeriesController.bTokenIndex(_seriesId) or SeriesController.wTokenIndex(_seriesId)

amounts

uint256[] memory

The amounts of option tokens to mint, in base units. The decimals will always be the same as the Series' underlying token'

data

bytes memory

Arbitrary data to be used by the individual ERC1155 token. For the SIREN protocol this can always unused, so it can be an empty array

burn

function burn(
address account,
uint256 id,
uint256 amount
)
public
override(ERC1155BurnableUpgradeable, IERC1155Controller)
onlySeriesController

Destroys amount tokens of token type id owned by the address account. account cannot be the zero address, and account must have at least amount of the tokens for this call to succeed. If the caller is not account, then account must have approved the caller using setApprovalForAll prior to calling burn.

The SeriesController calls this inside of SeriesController.exerciseOption and SeriesController.claimCollateral.

Parameters

Name

Type

Description

to

account

The address which will have the option tokens removed from it

id

uint256

The identifier of the option token. Can be obtained by either SeriesController.bTokenIndex(_seriesId) or SeriesController.wTokenIndex(_seriesId)

amount

uint256

The amount of option token to burn, in base units. The decimals will always be the same as the Series' underlying token'

burnBatch

function burnBatch(
address account,
uint256[] memory ids,
uint256[] memory amounts
)
public
override(ERC1155BurnableUpgradeable, IERC1155Controller)
onlySeriesController

Similar to burn, but more gas efficient when multiple transactions for different amounts of different token ids must be removed from the same account address. Use this function rather than burn when the caller wants to save gas while burning multiple tokens from the same address.

The SeriesController calls this inside of SeriesController.closePosition.

Parameters

Name

Type

Description

to

account

The address which will have the option tokens removed from it

ids

uint256[] memory

The identifiers of the option token. Can be obtained by either SeriesController.bTokenIndex(_seriesId) or SeriesController.wTokenIndex(_seriesId)

amounts

uint256[] memory

The amounts of option token to burn, in base units. The decimals will always be the same as the Series' underlying token'

updateImplementation

function updateImplementation(
address _newImplementation
) external onlyOwner

Updates this ERC1155Controller's logic contract. The SIREN protocol's contracts use the EIP-1822 standard for implementing upgradeable contracts. This allows us to update vulnerable contracts and keep users' option tokens safe. When the SIREN protocol has reached a certain level of stability, we can remove these safety guards and ensure no one on the Siren team can swap out the smart contract functionality.

Parameters

Name

Type

Description

_newImplementation

address

The address of the new logic contract to use for the ERC1155Controller's function implementations

transferOwnership

function transferOwnership(address _newAdmin) external onlyOwner

Removes ownership from the current owner and assigns ownership to the _newAdmin address. See the onlyOwner modifier for the permissions granted to the protocol admin.

Parameters

Name

Type

Description

_newAdmin

address

The address of the new admin for this contract