diff --git a/EIPS/eip-1155.md b/EIPS/eip-1155.md index b12fb2c853ca5..ba4f55416a701 100644 --- a/EIPS/eip-1155.md +++ b/EIPS/eip-1155.md @@ -13,19 +13,19 @@ requires: 165 ## Simple Summary -A standard interface for contracts that manage multiple token types. A single deployed contract may include any combination of fungible tokens, non-fungible tokens, or other configurations (e.g. semi-fungible tokens). +A standard interface for contracts that manage multiple token types. A single deployed contract may include any combination of fungible tokens, non-fungible tokens or other configurations (e.g. semi-fungible tokens). ## Abstract -This standard outlines a smart contract interface that can represent any number of Fungible and Non-Fungible token types. Existing standards such as ERC-20 require deployment of separate contracts per token type. The ERC-721 standard's token ID is a single non-fungible index and the group of these non-fungibles is deployed as a single contract with settings for the entire collection. In contrast, the ERC-1155 Multi Token Standard allows for each token ID to represent a new configurable token type, which may have its own metadata, supply and other attributes. +This standard outlines a smart contract interface that can represent any number of fungible and non-fungible token types. Existing standards such as ERC-20 require deployment of separate contracts per token type. The ERC-721 standard's token ID is a single non-fungible index and the group of these non-fungibles is deployed as a single contract with settings for the entire collection. In contrast, the ERC-1155 Multi Token Standard allows for each token ID to represent a new configurable token type, which may have its own metadata, supply and other attributes. The `_id` argument contained in each function's argument set indicates a specific token or token type in a transaction. ## Motivation -Tokens standards like ERC-20 and ERC-721 require a separate contract to be deployed for each token type or collection. This places a lot of redundant bytecode on the Ethereum blockchain and limits certain functionality by the nature of separating each token contract into its own permissioned address. With the rise of blockchain games and platforms like Enjin Coin, game developers may be creating thousands of token types, and a new type of token standard is needed to support them. However, ERC-1155 is not specific to games, and many other applications can benefit from this flexibility. +Tokens standards like ERC-20 and ERC-721 require a separate contract to be deployed for each token type or collection. This places a lot of redundant bytecode on the Ethereum blockchain and limits certain functionality by the nature of separating each token contract into its own permissioned address. With the rise of blockchain games and platforms like Enjin Coin, game developers may be creating thousands of token types, and a new type of token standard is needed to support them. However, ERC-1155 is not specific to games and many other applications can benefit from this flexibility. -New functionality is possible with this design, such as transferring multiple token types at once, saving on transaction costs. Trading (escrow / atomic swaps) of multiple tokens can be built on top of this standard and it removes the need to "approve" individual token contracts separately. It is also easy to describe and mix multiple fungible or non-fungible token types in a single contract. +New functionality is possible with this design such as transferring multiple token types at once, saving on transaction costs. Trading (escrow / atomic swaps) of multiple tokens can be built on top of this standard and it removes the need to "approve" individual token contracts separately. It is also easy to describe and mix multiple fungible or non-fungible token types in a single contract. ## Specification @@ -115,7 +115,7 @@ interface ERC1155 /* is ERC165 */ { function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external; /** - @notice Get the balance of an account's Tokens. + @notice Get the balance of an account's tokens. @param _owner The address of the token holder @param _id ID of the token @return The _owner's balance of the token type requested @@ -125,7 +125,7 @@ interface ERC1155 /* is ERC165 */ { /** @notice Get the balance of multiple account/token pairs @param _owners The addresses of the token holders - @param _ids ID of the Tokens + @param _ids ID of the tokens @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair) */ function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory); @@ -140,7 +140,7 @@ interface ERC1155 /* is ERC165 */ { /** @notice Queries the approval status of an operator for a given owner. - @param _owner The owner of the Tokens + @param _owner The owner of the tokens @param _operator Address of authorized operator @return True if the operator is approved, false if not */ @@ -207,7 +207,7 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran **_Scenario#3 :_** The receiver does not implement the necessary `ERC1155TokenReceiver` interface function(s). * The transfer MUST be reverted with the one caveat below. - - If the tokens being sent are part of a hybrid implementation of another standard, that particular standard's rules on sending to a contract MAY now be followed instead. See "Compatibility with other standards" section. + - If the token(s) being sent are part of a hybrid implementation of another standard, that particular standard's rules on sending to a contract MAY now be followed instead. See "Compatibility with other standards" section. **_Scenario#4 :_** The receiver implements the necessary `ERC1155TokenReceiver` interface function(s) but returns an unknown value. * The transfer MUST be reverted. @@ -242,9 +242,9 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran - If the contract logic wishes to keep the ownership of the token(s) itself in this case it MAY do so. **_Scenario#9 :_** You are transferring tokens via a non-standard API call i.e. an implementation specific API and NOT `safeTransferFrom` or `safeBatchTransferFrom`. -* In this scenario all balance updates and events output rules are the same as if a standard function had been called. - - i.e. an external viewer should still be able to query a balance via a function and it be identical to the balance as determined by `TransferSingle` and `TransferBatch` events alone. -* If the receiver is a contract the `ERC1155TokenReceiver` hooks still need to be called on it and the return values respected the same as if a standard function had been called. +* In this scenario all balance updates and events output rules are the same as if a standard transfer function had been called. + - i.e. an external viewer MUST still be able to query the balance via a standard function and it MUST be identical to the balance as determined by `TransferSingle` and `TransferBatch` events alone. +* If the receiver is a contract the `ERC1155TokenReceiver` hooks still need to be called on it and the return values respected the same as if a standard transfer function had been called. - However while the `safeTransferFrom` or `safeBatchTransferFrom` functions MUST revert if a receiving contract does not implement the `ERC1155TokenReceiver` interface, a non-standard function MAY proceed with the transfer. - See "Implementation specific transfer API rules". @@ -377,7 +377,7 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran * The total value transferred from address `0x0` minus the total value transferred to `0x0` observed via the `TransferSingle` and `TransferBatch` events MAY be used by clients and exchanges to determine the "circulating supply" for a given token ID. * As mentioned above mint/create and burn/destroy operations are specialized transfers and so will likely be accomplished with custom transfer functions rather than `safeTransferFrom` or `safeBatchTransferFrom`. If so the "Implementation specific transfer API rules" section would be appropriate. - Even in a non-safe API and/or hybrid standards case the above event rules MUST still be adhered to when minting/creating or burning/destroying. -* A contract MAY skip calling the `ERC1155TokenReceiver` hook function(s) if the mint/create operation is transferring the token(s) to itself. In all other cases the `ERC1155TokenReceiver` rules MUST be followed as appropriate for the implementation (i.e. safe, custom and/or hybrid). +* A contract MAY skip calling the `ERC1155TokenReceiver` hook function(s) if the mint operation is transferring the token(s) to itself. In all other cases the `ERC1155TokenReceiver` rules MUST be followed as appropriate for the implementation (i.e. safe, custom and/or hybrid). ##### A solidity example of the keccak256 generated constants for the various magic values (these MAY be used by implementation): @@ -407,7 +407,7 @@ An important consideration is that even if the tokens are sent with another stan ### Metadata -The URI value allows for ID substitution by clients. If the string `{id}` exists in any URI, clients MUST replace this with the actual token ID in hexadecimal form. This allows for large number of tokens to use the same on-chain string by defining a URI once, for a large collection of tokens. +The URI value allows for ID substitution by clients. If the string `{id}` exists in any URI, clients MUST replace this with the actual token ID in hexadecimal form. This allows for a large number of tokens to use the same on-chain string by defining a URI once, for that large number of tokens. * The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix. * The string format of the substituted hexadecimal ID MUST be leading zero padded to 64 hex characters length if necessary. @@ -594,7 +594,7 @@ fr.json: ### Approval The function `setApprovalForAll` allows an operator to manage one's entire set of tokens on behalf of the approver. To permit approval of a subset of token IDs, an interface such as [ERC-1761 Scoped Approval Interface](https://eips.ethereum.org/EIPS/eip-1761) is suggested. -The counterpart `isApprovedForAll` provides introspection into status set by `setApprovalForAll`. +The counterpart `isApprovedForAll` provides introspection into any status set by `setApprovalForAll`. An owner SHOULD be assumed to always be able to operate on their own tokens regardless of approval status, so should SHOULD NOT have to call `setApprovalForAll` to approve themselves as an operator before they can operate on them. @@ -630,7 +630,7 @@ Restricting approval to a certain set of token IDs, quantities or other rules MA ## Usage -This standard can be used to represent multiple token types for an entire domain. Both Fungible and Non-Fungible tokens can be stored in the same smart-contract. +This standard can be used to represent multiple token types for an entire domain. Both fungible and non-fungible tokens can be stored in the same smart-contract. ### Batch Transfers @@ -648,13 +648,13 @@ The `balanceOfBatch` function allows clients to retrieve balances of multiple ow In order to keep storage requirements light for contracts implementing ERC-1155, enumeration (discovering the IDs and values of tokens) must be done using event logs. It is RECOMMENDED that clients such as exchanges and blockchain explorers maintain a local database containing the token ID, Supply, and URI at the minimum. This can be built from each TransferSingle, TransferBatch, and URI event, starting from the block the smart contract was deployed until the latest block. -ERC-1155 contracts must therefore carefully emit `TransferSingle` or `TransferBatch` events in any instance where tokens are created, minted, or destroyed. +ERC-1155 contracts must therefore carefully emit `TransferSingle` or `TransferBatch` events in any instance where tokens are created, minted, transferred or destroyed. ### Non-Fungible Tokens The following strategy is an example of how to mix fungible and non-fungible tokens together in the same contract. The top 128 bits of the uint256 `_id` parameter in any ERC-1155 function could represent the base token ID, while the bottom 128 bits might be used for any extra data passed to the contract. -Non-Fungible tokens can be interacted with using an index based accessor into the contract/token data set. Therefore to access a particular token set within a mixed data contract and particular NFT within that set, `_id` could be passed as ``. +Non-fungible tokens can be interacted with using an index based accessor into the contract/token data set. Therefore to access a particular token set within a mixed data contract and particular NFT within that set, `_id` could be passed as ``. Inside the contract code the two pieces of data needed to access the individual NFT can be extracted with uint128(~0) and the same mask shifted by 128. @@ -665,7 +665,7 @@ uint256 baseToken = 12345 << 128; uint128 index = 50; balanceOf(baseToken, msg.sender); // Get balance of the base token -balanceOf(baseToken + index, msg.sender); // Get balance of the Non-Fungible token index +balanceOf(baseToken + index, msg.sender); // Get balance of the non-fungible token index ``` ## References