Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added wighawag as an author, alter isERC1155Receiver interface to view instead of pure (to cover fallback versions), be clearer about having to pass the _data arg to the hooks unaltered, make it so all events have to be emitted before any hooks are called so order is preserved and added a scenario for the case of forwarding tokens in the receiver. #2049

Merged
merged 38 commits into from
May 18, 2019
Merged
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
49fbbde
EDT-3069 Adding more clarity in transfer rules and other things, alte…
AC0DEM0NK3Y May 3, 2019
5a0fba2
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 3, 2019
73a3365
EDT-3069 id substitution example was not lowercase.
AC0DEM0NK3Y May 4, 2019
0557c37
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 4, 2019
ed9f0d1
EDT-3069 Updated the "Safe Transfer Rules" section to match feedback …
AC0DEM0NK3Y May 7, 2019
e331f58
EDT-3069 Some formatting changes to make it easier to digest/
AC0DEM0NK3Y May 7, 2019
3e2a176
EDT-3069 More formatting.
AC0DEM0NK3Y May 7, 2019
c9db596
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 7, 2019
3ba6d4f
EDT-3069 Move impl specific functions rules to the rules section.
AC0DEM0NK3Y May 7, 2019
b3f5675
EDT-3069 Better wording on impl specific api rules.
AC0DEM0NK3Y May 7, 2019
774c0ae
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 7, 2019
f745443
EDT-3069 Added in rules for TransferSingle and TransferBatch events s…
AC0DEM0NK3Y May 7, 2019
1f3a415
EDT-3069 EOA explanation.
AC0DEM0NK3Y May 8, 2019
54a4fa1
EDT-3069 Updated text after feedback.
AC0DEM0NK3Y May 9, 2019
2f16e0f
EDT-3069 Another update.
AC0DEM0NK3Y May 9, 2019
cdc350b
EDT- Minor wording changes, be consistent in how we name ERC numbers …
AC0DEM0NK3Y May 9, 2019
5083d1e
EDT-3069 Remove confusion on hook return vals and args.
AC0DEM0NK3Y May 9, 2019
5869a76
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 9, 2019
cbc7264
EDT-3069 Drop the "DRAFT" text from linked standards, so when we go f…
AC0DEM0NK3Y May 9, 2019
d5446f9
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 9, 2019
c62f69b
EDT-3069 Added safe and batch transferFrom rules to also be explicit …
AC0DEM0NK3Y May 9, 2019
dd6b5d7
EDT-3069 Another small change to match the rules.
AC0DEM0NK3Y May 9, 2019
4f36207
Changes to wording to clarify transfer rules.
JamesTherien May 10, 2019
b6f8829
Clarification for the _data parameter
JamesTherien May 10, 2019
67a42bc
Clarify rules of breaking down into multiple onReceived callbacks
JamesTherien May 10, 2019
8f0c356
Merge pull request #1 from JamesTherien/master
AC0DEM0NK3Y May 10, 2019
48cce31
EDT-3069 Alter the rejection logic back to normal for regular 115 ope…
AC0DEM0NK3Y May 10, 2019
f11b5c2
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 10, 2019
cd86485
EDT-3069 Small inconsistency and remove the ==<hex value> part from r…
AC0DEM0NK3Y May 11, 2019
206594c
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 11, 2019
d7b07bd
EDT-3069 Add in ERC-165 interface identifier info for the ERC1155Toke…
AC0DEM0NK3Y May 11, 2019
97fa9de
EDT-3069 Very minor change to text, remove odd grammar.
AC0DEM0NK3Y May 13, 2019
4f0378e
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 13, 2019
15a67ab
EDT-3069 Consistency change on the isERC1155TokenReceiver gas require…
AC0DEM0NK3Y May 13, 2019
65052c6
EDT-3069 Added wighawag as an author, alter isERC1155Receiver interfa…
AC0DEM0NK3Y May 18, 2019
8cb2756
EDT-3069 Minor grammar and consistency changes on use of "for example…
AC0DEM0NK3Y May 18, 2019
a560f91
EDT-3069 Change the recommended isERC1155TokenReceiver function to us…
AC0DEM0NK3Y May 18, 2019
2eedafb
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 34 additions & 22 deletions EIPS/eip-1155.md
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
Expand All @@ -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

Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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

Expand All @@ -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

Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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()"))
}
```
Expand Down