Skip to content

Commit

Permalink
Automatically merged updates to draft EIP(s) 1155 (ethereum#2096)
Browse files Browse the repository at this point in the history
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
AC0DEM0NK3Y authored and ilanolkies committed Nov 12, 2019
1 parent 6ed4e42 commit d588d27
Showing 1 changed file with 37 additions and 14 deletions.
51 changes: 37 additions & 14 deletions EIPS/eip-1155.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ interface ERC1155 /* is ERC165 */ {

### ERC-1155 Token Receiver

Smart contracts **MUST** implement this interface to accept transfers. See "Safe Transfer Rules" for further detail.
Smart contracts **MUST** implement all the functions in this interface to accept transfers. See "Safe Transfer Rules" for further detail.

```solidity
pragma solidity ^0.5.9;
Expand Down Expand Up @@ -283,8 +283,8 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran
- The `_to` argument MUST be the address of the recipient whose balance is increased.
- 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.
- When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
- When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
- When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). See "Minting/creating and burning/destroying rules".
- When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). See "Minting/creating and burning/destroying rules".
* `TransferBatch` SHOULD be used to indicate multiple balance transfers have occurred between a `_from` and `_to` pair.
- It MAY be emitted with a single element in the list to indicate a singular balance change in the transaction, but note that `TransferSingle` is designed for this to reduce gas consumption.
- The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
Expand All @@ -293,9 +293,9 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran
- The `_ids` array argument MUST contain the ids of the tokens being transferred.
- The `_values` array argument MUST contain the number of token to be transferred for each corresponding entry in `_ids`.
- `_ids` and `_values` MUST have the same length.
- When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
- 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.
- When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). See "Minting/creating and burning/destroying rules".
- When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). See "Minting/creating and burning/destroying rules".
* 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.
* 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.
Expand All @@ -316,6 +316,7 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran
* `onERC1155Received` (and/or `onERC1155BatchReceived`) MAY be called multiple times in a single transaction and the following requirements must be met:
- All callbacks represent mutually exclusive balance changes.
- 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 `onERC1155Received` hook function if the transfer operation is transferring the token to itself.

**_onERC1155BatchReceived rules:_**
- The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
Expand All @@ -333,6 +334,7 @@ To be more explicit about how the standard `safeTransferFrom` and `safeBatchTran
* `onERC1155BatchReceived` (and/or `onERC1155Received`) MAY be called multiple times in a single transaction and the following requirements must be met:
- All callbacks represent mutually exclusive balance changes.
- 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:
Expand All @@ -354,15 +356,31 @@ 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.
8. If the above call to `isERC1155TokenReceiver()` on `_to` reverts or returns an unknown value 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).
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.
- __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.
- A receiver address has to be checked if it is a contract and if so relevant `ERC1155TokenReceiver` hook function(s) have to be called on it.
- Balances (and events associated) that are referenced in a call to an `ERC1155TokenReceiver` hook MUST be updated (and emitted) before the `ERC1155TokenReceiver` hook is called.
- The return values of the `ERC1155TokenReceiver` hook functions that are called MUST be respected if they are implemented.
- Only non-standard transfer functions MAY allow tokens to be sent to a recipient contract that does NOT implement the necessary `ERC1155TokenReceiver` hook functions. `safeTransferFrom` and `safeBatchTransferFrom` MUST revert in that case (unless it is a hybrid standards implementation see "Compatibility with other standards").

**_Minting/creating and burning/destroying rules:_**
* A mint/create operation is essentially a specialized transfer and MUST follow these rules:
- 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.
- The "TransferSingle and TransferBatch event rules" MUST be followed as appropriate for the mint(s) (i.e. singles or batches) however the `_from` argument MUST be set to `0x0` (i.e. zero address) to flag the transfer as a mint to contract observers.
- __NOTE:__ This includes tokens that are given an initial balance in the contract. The balance of the contract MUST also be able to be determined by events alone meaning initial contract balances (for eg. in construction) MUST emit events to reflect those balances too.

* A burn/destroy operation is essentially a specialized transfer and MUST follow these rules:
- The "TransferSingle and TransferBatch event rules" MUST be followed as appropriate for the burn(s) (i.e. singles or batches) however the `_to` argument MUST be set to `0x0` (i.e. zero address) to flag the transfer as a burn to contract observers.
- NOTE: When burning/destroying you do not have to actually transfer to `0x0` (that is impl specific), only the `_to` argument in the event MUST be set to `0x0` as above.
* 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 a 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 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)"))
Expand All @@ -386,10 +404,12 @@ 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. Example of such a URI: `https://token-cdn-domain/{id}.json` would be replaced with `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` if the client is referring to token ID 314592/0x4CCE0.
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 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.

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.
Example of such a URI: `https://token-cdn-domain/{id}.json` would be replaced with `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` if the client is referring to token ID 314592/0x4CCE0.

#### Metadata Extensions

Expand Down Expand Up @@ -418,7 +438,8 @@ interface ERC1155Metadata_URI {

This JSON schema is loosely based on the "ERC721 Metadata JSON Schema", but includes optional formatting to allow for ID substitution by clients. If the string `{id}` exists in any JSON value, it MUST be replaced with the actual token ID, by all client software that follows this standard.

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 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.

```json
{
Expand Down Expand Up @@ -605,13 +626,15 @@ This standard can be used to represent multiple token types for an entire domain

### Batch Transfers

The `safeBatchTransferFrom` function allows for batch transfers of multiple token ids and values. The design of ERC-1155 makes batch transfers possible without the need for a wrapper contract, as with existing token standards. This reduces gas costs when more than one token type is included in a batch transfer, as compared to single transfers with multiple transactions.
The `safeBatchTransferFrom` function allows for batch transfers of multiple token IDs and values. The design of ERC-1155 makes batch transfers possible without the need for a wrapper contract, as with existing token standards. This reduces gas costs when more than one token type is included in a batch transfer, as compared to single transfers with multiple transactions.

Another advantage of standardized batch transfers is the ability for a smart contract to respond to the batch transfer in a single operation using `onERC1155BatchReceived`.

It is RECOMMENDED that clients and wallets sort the token IDs and associated values (in ascending order) when posting a batch transfer, as some ERC-1155 implementations offer significant gas cost savings when IDs are sorted. See [Horizon Games - Multi-Token Standard](https://github.com/horizon-games/multi-token-standard) "packed balance" implementation for an example of this.

### Batch Balance

The `balanceOfBatch` function allows clients to retrieve balances of multiple owners and token ids with a single call.
The `balanceOfBatch` function allows clients to retrieve balances of multiple owners and token IDs with a single call.

### Enumerating from events

Expand Down

0 comments on commit d588d27

Please sign in to comment.