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

Replace isERCTokenReceiver with usage of ERC165 supportsInterface. #2108

Merged
merged 77 commits into from
Jun 7, 2019
Merged
Changes from all commits
Commits
Show all changes
77 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
cc3e971
EDT-3069 Small alteration to text by request.
AC0DEM0NK3Y May 21, 2019
c2a0f11
EDT-3069 Minor text consistency change.
AC0DEM0NK3Y May 22, 2019
4eaf2c7
EDT-3069 Fixed typo.
AC0DEM0NK3Y May 22, 2019
fb0e643
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 22, 2019
cc3a9d9
EDT-3069 Spelling.
AC0DEM0NK3Y May 22, 2019
caa8d27
EDT-3069 Minor formatting change.
AC0DEM0NK3Y May 22, 2019
d8b0d2f
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 22, 2019
8c96bfb
EDT-3069 Some small changes to wording for clarity.
AC0DEM0NK3Y May 24, 2019
282e0d0
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 24, 2019
50d401c
Revert magic_values to original byte4
PhABC May 24, 2019
d054f84
EDT-3069 Adding in scenario for non-standard api call and allow it to…
AC0DEM0NK3Y May 24, 2019
8d50450
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 25, 2019
eb36a93
Merge pull request #2 from PhABC/patch-7
AC0DEM0NK3Y May 25, 2019
ca3278b
EDT-3069 Minor consistency change.
AC0DEM0NK3Y May 25, 2019
cfae695
EDT-3069 Updated return value to latest after merge.
AC0DEM0NK3Y May 25, 2019
c21e799
EDT-3069 Consistency on calling "1155" "ERC-1155".
AC0DEM0NK3Y May 25, 2019
6dd5dc6
EDT-3069 Minor wording change.
AC0DEM0NK3Y May 25, 2019
343457a
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 25, 2019
91815a0
EDT-3069 More wording changes for clarification.
AC0DEM0NK3Y May 25, 2019
a3c61ba
EDT-3069 Small grammar change and capitalized API.
AC0DEM0NK3Y May 25, 2019
4ff6c62
EDT-3069 Change a MAY to SHOULD as a non-standard impl really should …
AC0DEM0NK3Y May 25, 2019
2a62512
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 25, 2019
4da1425
EDT-3069 Minor changes for grammar and consistency.
AC0DEM0NK3Y May 26, 2019
4aa3ac9
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 27, 2019
7a61926
EDT-3069 Slightly strong wording using SHOULD instead of a MAY in the…
AC0DEM0NK3Y May 27, 2019
a301bc6
EDT-3069 Solidity 0.5.9 is latest version (ref impl tested on this ve…
AC0DEM0NK3Y May 28, 2019
a9b6921
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 28, 2019
0ec4c57
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y May 28, 2019
16ad5b1
EDT-3069 Some alteration to the standard as requested along with a se…
AC0DEM0NK3Y Jun 1, 2019
eb1207b
EDT-3069 Minor grammar fix.
AC0DEM0NK3Y Jun 3, 2019
219d72a
EDT-3069 Add in mention that mint/burn is a custom transfer so follow…
AC0DEM0NK3Y Jun 4, 2019
e57d757
EDT-3069 Add in recommendation for wallets etc. to sort their batch t…
AC0DEM0NK3Y Jun 4, 2019
7800e85
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y Jun 4, 2019
8390de7
EDT-3069 More minor grammar and formatting fixes.
AC0DEM0NK3Y Jun 4, 2019
93cc841
DT-3069 Consistent use of MUST in uri event and function.
AC0DEM0NK3Y Jun 5, 2019
34df030
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y Jun 5, 2019
4f21e38
EDT-3069 Replace isERCTokenReceiver with usage of ERC165 supportsInte…
AC0DEM0NK3Y Jun 6, 2019
9de300a
Merge branch 'master' of https://github.com/ethereum/EIPs
AC0DEM0NK3Y Jun 7, 2019
463d6b2
URI event clarification
AC0DEM0NK3Y Jun 7, 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
59 changes: 31 additions & 28 deletions EIPS/eip-1155.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,13 @@ interface ERC1155 /* is ERC165 */ {
### ERC-1155 Token Receiver

Smart contracts **MUST** implement all the functions in this interface to accept transfers. See "Safe Transfer Rules" for further detail.
Smart contracts **MUST** implement the ERC-165 `supportsInterface` function and signify support for this interface. See "ERC1155TokenReceiver ERC-165 rules" for further detail.

```solidity
pragma solidity ^0.5.9;

/**
Note: The ERC-165 identifier for this interface is 0x43b236a2.
Note: The ERC-165 identifier for this interface is 0x4e2312e0.
*/
interface ERC1155TokenReceiver {
/**
Expand Down Expand Up @@ -185,15 +186,7 @@ interface ERC1155TokenReceiver {
@param _data Additional data with no specified format
@return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
*/
function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4);

/**
@notice Indicates whether a contract implements the `ERC1155TokenReceiver` functions and so can accept ERC1155 token types.
@dev This function MUST return `bytes4(keccak256("isERC1155TokenReceiver()"))` (i.e. 0x0d912442).
This function MUST NOT consume more than 5,000 gas.
@return `bytes4(keccak256("isERC1155TokenReceiver()"))`
*/
function isERC1155TokenReceiver() external view returns (bytes4);
function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4);
}
```

Expand Down Expand Up @@ -336,16 +329,19 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran
- The set of all calls to `onERC1155Received` and `onERC1155BatchReceived` describes all balance changes that occurred during the transaction in the order submitted.
* A contract MAY skip calling the `onERC1155BatchReceived` hook function if the transfer operation is transferring the token(s) to itself.

**_isERC1155TokenReceiver rules:_**
* The implementation of `isERC1155TokenReceiver` function SHOULD be as follows:
```
function isERC1155TokenReceiver() external view returns (bytes4) {
return 0x0d912442; // bytes4(keccak256("isERC1155TokenReceiver()"))
**_ERC1155TokenReceiver ERC-165 rules:_**
* The implementation of the ERC-165 `supportsInterface` function SHOULD be as follows:
```
function supportsInterface(bytes4 interfaceID) external view returns (bool) {
return interfaceID == 0x01ffc9a7 || // ERC-165 support (i.e. `bytes4(keccak256('supportsInterface(bytes4)'))`).
interfaceID == 0x4e2312e0; // ERC-1155 `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) ^ bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`).
}
```
```
* The implementation MAY differ from the above but:
- It MUST return the same value.
- It MUST NOT consume more than 5,000 gas.
- It MUST return the constant value `true` if `0x01ffc9a7` is passed through the `interfaceID` argument. This signifies ERC-165 support.
- It MUST return the constant value `true` if `0x4e2312e0` is passed through the `interfaceID` argument. This signifies ERC-1155 `ERC1155TokenReceiver` support.
- It MUST NOT consume more than 10,000 gas.
- This keeps it below the ERC-165 requirement of 30,000 gas, reduces the gas reserve needs and minimises possible side-effects of gas exhaustion during the call.

**_Implementation specific transfer API rules:_**
* If an implementation specific API function is used to transfer ERC-1155 token(s) to a contract, the `safeTransferFrom` or `safeBatchTransferFrom` (as appropriate) rules MUST still be followed if the receiver implements the `ERC1155TokenReceiver` interface. If it does not the non-standard implementation SHOULD revert but MAY proceed.
Expand All @@ -356,9 +352,9 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran
4. `myTransferFrom` checks if `_to` is a contract address and determines that it is so (if not, then the transfer can be considered successful).
5. `myTransferFrom` calls `onERC1155BatchReceived` on `_to` and it reverts or returns an unknown value (if it had returned `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` the transfer can be considered successful).
6. At this point `myTransferFrom` SHOULD revert the transaction immediately as receipt of the token(s) was not explicitly accepted by the `onERC1155BatchReceived` function.
7. If however `myTransferFrom` wishes to continue it MUST call `isERC1155TokenReceiver()` on `_to` and if it returns `bytes4(keccak256("isERC1155TokenReceiver()"))` the transaction MUST be reverted, as it is now known to be a valid receiver and the previous acceptance step failed.
- NOTE: You could have called `isERC1155TokenReceiver()` at a previous step if you wanted to gather and act upon that information earlier, such as in a hybrid standards scenario.
8. If the above call to `isERC1155TokenReceiver()` on `_to` reverts or returns an unknown value the `myTransferFrom` function MAY consider this transfer successful.
7. If however `myTransferFrom` wishes to continue it MUST call `supportsInterface(0x4e2312e0)` on `_to` and if it returns the constant value `true` the transaction MUST be reverted, as it is now known to be a valid receiver and the previous acceptance step failed.
- NOTE: You could have called `supportsInterface(0x4e2312e0)` at a previous step if you wanted to gather and act upon that information earlier, such as in a hybrid standards scenario.
8. If the above call to `supportsInterface(0x4e2312e0)` on `_to` reverts or returns a value other than the constant value `true` the `myTransferFrom` function MAY consider this transfer successful.
- __NOTE__: this MAY result in unrecoverable tokens if sent to an address that does not expect to receive ERC-1155 tokens.
* The above example is not exhaustive but illustrates the major points (and shows that most are shared with `safeTransferFrom` and `safeBatchTransferFrom`):
- Balances that are updated MUST have equivalent transfer events emitted.
Expand All @@ -381,20 +377,25 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran
* 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 solidity example of the keccak256 generated constants for the return magic is:
- bytes4 constant public ERC1155_ACCEPTED = 0xf23a6e61; // bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))
- bytes4 constant public ERC1155_BATCH_ACCEPTED = 0xbc197c81; // bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))
##### A solidity example of the keccak256 generated constants for the various magic values (these MAY be used by implementation):

```
bytes4 constant public ERC1155_ERC165 = 0xd9b67a26; // ERC-165 identifier for the main token standard.
bytes4 constant public ERC1155_ERC165_TOKENRECEIVER = 0x4e2312e0; // ERC-165 identifier for the `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) ^ bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`).
bytes4 constant public ERC1155_ACCEPTED = 0xf23a6e61; // Return value from `onERC1155Received` call if a contract accepts receipt (i.e `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`).
bytes4 constant public ERC1155_BATCH_ACCEPTED = 0xbc197c81; // Return value from `onERC1155BatchReceived` call if a contract accepts receipt (i.e `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`).
```

#### Compatibility with other standards

There have been requirements during the design discussions to have this standard be compatible with existing standards when sending to contract addresses, specifically ERC-721 at time of writing.
To cater for this scenario, there is some leeway with the rejection logic should a contract not implement the `ERC1155TokenReceiver` as per "Safe Transfer Rules" section above, specifically "Scenario#3 : The receiver does not implement the necessary `ERC1155TokenReceiver` interface function(s)".
To cater for this scenario, there is some leeway with the revert logic should a contract not implement the `ERC1155TokenReceiver` as per "Safe Transfer Rules" section above, specifically "Scenario#3 : The receiver does not implement the necessary `ERC1155TokenReceiver` interface function(s)".

Hence in a hybrid ERC-1155 contract implementation an extra call MUST be made on the recipient contract and checked before any hook calls to `onERC1155Received` or `onERC1155BatchReceived` are made.
Order of operation MUST therefore be:
1. The implementation MUST call the function `isERC1155TokenReceiver` on the recipient contract, providing at least 5,000 gas.
2. If the function call succeeds and the return value is `bytes4(keccak256("isERC1155TokenReceiver()"))` the implementation proceeds as a regular ERC-1155 implementation, with the call(s) to the `onERC1155Received` or `onERC1155BatchReceived` hooks and rules associated.
3. If the function call fails or the return value is NOT `bytes4(keccak256("isERC1155TokenReceiver()"))` the implementation can assume the recipient contract is not an `ERC1155TokenReceiver` and follow its other standard's rules for transfers.
1. The implementation MUST call the function `supportsInterface(0x4e2312e0)` on the recipient contract, providing at least 10,000 gas.
2. If the function call succeeds and the return value is the constant value `true` the implementation proceeds as a regular ERC-1155 implementation, with the call(s) to the `onERC1155Received` or `onERC1155BatchReceived` hooks and rules associated.
3. If the function call fails or the return value is NOT the constant value `true` the implementation can assume the recipient contract is not an `ERC1155TokenReceiver` and follow its other standard's rules for transfers.

*__Note that a pure implementation of a single standard is recommended__* rather than a hybrid solution, but an example of a hybrid ERC-1155/ERC-721 contract is linked in the references section under implementations.

Expand All @@ -416,6 +417,8 @@ The following optional extensions can be identified with the (ERC-165 Standard I

Changes to the URI MUST emit the `URI` event if the change can be expressed with an event (i.e. it isn't dynamic). If the optional ERC1155Metadata_URI extension is included, the `uri` function SHOULD be used to retrieve values for which no event was emitted. The function MUST return the same value as the event if it was emitted.

Note that if this extension is enabled: if the URI event is to be used for metadata uri's changes, it does not need to be emitted first at Mint time. Observer can fetch the metadata uri at mint time from the `uri` function.

```solidity
pragma solidity ^0.5.9;

Expand Down