forked from ethereum/EIPs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automatically merged updates to draft EIP(s) 1155 (ethereum#2049)
Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing
- Loading branch information
1 parent
9ed4e96
commit 5e6d488
Showing
1 changed file
with
34 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
--- | ||
eip: 1155 | ||
title: ERC-1155 Multi Token Standard | ||
author: Witek Radomski <[email protected]>, Andrew Cooke <[email protected]>, Philippe Castonguay <[email protected]>, James Therien <[email protected]>, Eric Binet <[email protected]> | ||
author: Witek Radomski <[email protected]>, Andrew Cooke <[email protected]>, Philippe Castonguay <[email protected]>, James Therien <[email protected]>, Eric Binet <[email protected]>, Ronan Sandford <[email protected]> | ||
type: Standards Track | ||
category: ERC | ||
status: Draft | ||
|
@@ -13,7 +13,7 @@ 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 (for example, 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 | ||
|
||
|
@@ -84,13 +84,13 @@ interface ERC1155 /* is ERC165 */ { | |
MUST revert if `_to` is the zero address. | ||
MUST revert if balance of holder for token `_id` is lower than the `_value` sent. | ||
MUST revert on any other error. | ||
After the above conditions are met, this function MUST check if `_to` is a smart contract (eg. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). | ||
MUST emit `TransferSingle` event on transfer success (see "Safe Transfer Rules" section of the standard). | ||
MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard). | ||
After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). | ||
@param _from Source address | ||
@param _to Target address | ||
@param _id ID of the token type | ||
@param _value Transfer amount | ||
@param _data Additional data with no specified format, MUST be sent in call to `onERC1155Received` on `_to` | ||
@param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to` | ||
*/ | ||
function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external; | ||
|
@@ -100,15 +100,15 @@ interface ERC1155 /* is ERC165 */ { | |
MUST revert if `_to` is the zero address. | ||
MUST revert if length of `_ids` is not the same as length of `_values`. | ||
MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient. | ||
MUST revert on any other error. | ||
Transfers and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc). | ||
After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (eg. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). | ||
MUST emit `TransferSingle` or `TransferBatch` event(s) on transfer success (see "Safe Transfer Rules" section of the standard). | ||
MUST revert on any other error. | ||
MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard). | ||
Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc). | ||
After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). | ||
@param _from Source address | ||
@param _to Target address | ||
@param _ids IDs of each token type (order and length must match _values array) | ||
@param _values Transfer amounts per token type (order and length must match _ids array) | ||
@param _data Additional data with no specified format, MUST be sent in call to the `ERC1155TokenReceiver` hook(s) on `_to` | ||
@param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to` | ||
*/ | ||
function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external; | ||
|
@@ -193,13 +193,13 @@ interface ERC1155TokenReceiver { | |
This function MUST NOT consume more than 5,000 gas. | ||
@return `bytes4(keccak256("isERC1155TokenReceiver()"))` | ||
*/ | ||
function isERC1155TokenReceiver() external pure returns (bytes4); | ||
function isERC1155TokenReceiver() external view returns (bytes4); | ||
} | ||
``` | ||
|
||
### Safe Transfer Rules | ||
|
||
To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST operate with respect to the `ERC1155TokenReceiver`, a list of scenarios and rules follows. | ||
To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST operate with respect to the `ERC1155TokenReceiver` hook functions, a list of scenarios and rules follows. | ||
|
||
#### Scenarios | ||
|
||
|
@@ -219,22 +219,30 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op | |
**_Scenario#5 :_** The receiver implements the necessary `ERC1155TokenReceiver` interface function(s) but throws an error. | ||
* The transfer MUST be reverted. | ||
|
||
**_Scenario#6 :_** The receiver implements the `ERC1155TokenReceiver` interface and is the recipient of one and only one balance change (eg. safeTransferFrom called). | ||
**_Scenario#6 :_** The receiver implements the `ERC1155TokenReceiver` interface and is the recipient of one and only one balance change (e.g. safeTransferFrom called). | ||
* All the balances in the transfer MUST have been updated to match the senders intent before any hook is called on a recipient. | ||
* All the transfer events for the transfer MUST have been emitted to reflect the balance changes before any hook is called on a recipient. | ||
* One of `onERC1155Received` or `onERC1155BatchReceived` MUST be called on the recipient. | ||
* The `onERC1155Received` hook SHOULD be called on the recipient contract and its rules followed. | ||
- See "onERC1155Received rules" for further rules that MUST be followed. | ||
* The `onERC1155BatchReceived` hook MAY be called on the recipient contract and its rules followed. | ||
- See "onERC1155BatchReceived rules" for further rules that MUST be followed. | ||
|
||
**_Scenario#7 :_** The receiver implements the `ERC1155TokenReceiver` interface and is the recipient of more than one balance change (eg. safeBatchTransferFrom called). | ||
**_Scenario#7 :_** The receiver implements the `ERC1155TokenReceiver` interface and is the recipient of more than one balance change (e.g. safeBatchTransferFrom called). | ||
* All the balances in the transfer MUST have been updated to match the senders intent before any hook is called on a recipient. | ||
* All the transfer events for the transfer MUST have been emitted to reflect the balance changes before any hook is called on a recipient. | ||
* `onERC1155Received` or `onERC1155BatchReceived` MUST be called on the recipient as many times as necessary such that every balance change for the recipient in the scenario is accounted for. | ||
- The return magic value for every hook call MUST be checked and acted upon as per "onERC1155Received rules" and "onERC1155BatchReceived rules". | ||
* The `onERC1155BatchReceived` hook SHOULD be called on the recipient contract and its rules followed. | ||
- See "onERC1155BatchReceived rules" for further rules that MUST be followed. | ||
* The `onERC1155Received` hook MAY be called on the recipient contract and its rules followed. | ||
- See "onERC1155Received rules" for further rules that MUST be followed. | ||
|
||
**_Scenario#8 :_** You are the creator of a contract that implements the `ERC1155TokenReceiver` interface and you forward the token(s) onto another address in one or both of `onERC1155Received` and `onERC1155BatchReceived`. | ||
* Forwarding should be considered acceptance and then initiating a new `safeTransferFrom` or `safeBatchTransferFrom` in a new context. | ||
- The prescribed keccak256 acceptance value magic for the receiver hook being called MUST be returned after forwarding is successful. | ||
* The `_data` argument MAY be re-purposed for the new context. | ||
* If forwarding unexpectedly fails the transaction MUST be reverted. | ||
|
||
#### Rules | ||
|
||
|
@@ -243,18 +251,18 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op | |
* MUST revert if `_to` is the zero address. | ||
* MUST revert if balance of holder for token `_id` is lower than the `_value` sent to the recipient. | ||
* MUST revert on any other error. | ||
* After the above conditions are met, this function MUST check if `_to` is a smart contract (eg. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "onERC1155Received rules" section). | ||
* MUST emit `TransferSingle` event on transfer success (see "TransferSingle and TransferBatch event rules" section). | ||
* MUST emit the `TransferSingle` event to reflect the balance change (see "TransferSingle and TransferBatch event rules" section). | ||
* After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "onERC1155Received rules" section). | ||
|
||
**_safeBatchTransferFrom rules:_** | ||
* Caller must be approved to manage all the tokens being transferred out of the `_from` account (see "Approval" section). | ||
* MUST revert if `_to` is the zero address. | ||
* MUST revert if length of `_ids` is not the same as length of `_values`. | ||
* MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient. | ||
* MUST revert on any other error. | ||
* After the above conditions are met, this function MUST check if `_to` is a smart contract (eg. code size > 0). If so, it MUST call `onERC1155Received` or `onERC1155BatchReceived` on `_to` and act appropriately (see "`onERC1155Received` and onERC1155BatchReceived rules" section). | ||
* MUST emit `TransferSingle` or `TransferBatch` event(s) on transfer success (see "TransferSingle and TransferBatch event rules" section). | ||
* Transfers and events MUST occur in the array order they were submitted (_ids[0]/_values[0] before _ids[1]/_values[1], etc). | ||
* MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "TransferSingle and TransferBatch event rules" section). | ||
* The balance changes and events MUST occur in the array order they were submitted (_ids[0]/_values[0] before _ids[1]/_values[1], etc). | ||
* After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` or `onERC1155BatchReceived` on `_to` and act appropriately (see "`onERC1155Received` and onERC1155BatchReceived rules" section). | ||
|
||
**_TransferSingle and TransferBatch event rules:_** | ||
* `TransferSingle` SHOULD be used to indicate a single balance transfer has occurred between a `_from` and `_to` pair. | ||
|
@@ -278,14 +286,17 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op | |
- When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). | ||
* The total value transferred from address 0x0 minus the total value transferred to 0x0 MAY be used by clients and exchanges to be added to the "circulating supply" for a given token ID. | ||
* To broadcast the existence of a token ID with no initial balance, the contract SHOULD emit the `TransferSingle` event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_value` of 0. | ||
* All `TransferSingle` and `TransferBatch` events MUST be emitted to reflect all the balance changes that have occurred before any call(s) to `onERC1155Received` or `onERC1155BatchReceived`. | ||
- To make sure event order is correct in the case of valid re-entry (e.g. if a receiver contract forwards tokens on receipt) state balance and events balance MUST match before calling an external contract. | ||
|
||
**_onERC1155Received rules:_** | ||
* The `_operator` argument MUST be the address of the account/contract that initiated the transfer (i.e. msg.sender). | ||
* The `_from` argument MUST be the address of the holder whose balance is decreased. | ||
- `_from` MUST be 0x0 for a mint. | ||
* The `_id` argument MUST be the token type being transferred. | ||
* The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by. | ||
* The `_data` argument MUST contain the extra information provided by the sender for the transfer. | ||
* The `_data` argument MUST contain the unaltered information provided by the sender for the transfer. | ||
- i.e. it MUST pass on the unaltered `_data` argument sent via the `safeTransferFrom` or `safeBatchTransferFrom` call for this transfer. | ||
* The recipient contract MAY accept an increase of its balance by returning the acceptance magic value `bytes4(keccak256("accept_erc1155_tokens()"))` | ||
- If the return value is `bytes4(keccak256("accept_erc1155_tokens()"))` the transfer MUST be completed or MUST revert if any other conditions are not met for success. | ||
* The recipient contract MAY reject an increase of its balance by calling revert. | ||
|
@@ -301,7 +312,8 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op | |
- `_from` MUST be 0x0 for a mint. | ||
* The `_ids` argument MUST be the list of tokens being transferred. | ||
* The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in `_ids`) the holder balance is decreased by and match what the recipient balance is increased by. | ||
* The `_data` argument MUST contain the information provided by the sender for a transfer. | ||
* The `_data` argument MUST contain the unaltered information provided by the sender for the transfer. | ||
- i.e. it MUST pass on the unaltered `_data` argument sent via the `safeTransferFrom` or `safeBatchTransferFrom` call for this transfer. | ||
* The recipient contract MAY accept an increase of its balance by returning the acceptance magic value `bytes4(keccak256("accept_batch_erc1155_tokens()"))` | ||
- If the return value is `bytes4(keccak256("accept_batch_erc1155_tokens()"))` the transfer MUST be completed or MUST revert if any other conditions are not met for success. | ||
* The recipient contract MAY reject an increase of its balance by calling revert. | ||
|
@@ -314,7 +326,7 @@ To be more explicit about how safeTransferFrom and safeBatchTransferFrom MUST op | |
**_isERC1155TokenReceiver rules:_** | ||
* The implementation of `isERC1155TokenReceiver` function SHOULD be as follows: | ||
``` | ||
function isERC1155TokenReceiver() external pure returns (bytes4) { | ||
function isERC1155TokenReceiver() external view returns (bytes4) { | ||
return 0x0d912442; // bytes4(keccak256("isERC1155TokenReceiver()")) | ||
} | ||
``` | ||
|