122 lines
9.1 KiB
Markdown
122 lines
9.1 KiB
Markdown
---
|
||
eip: 2309
|
||
title: ERC-721 Consecutive Transfer Extension
|
||
author: Sean Papanikolas (@pizzarob)
|
||
discussions-to: https://github.com/ethereum/EIPs/issues/2309
|
||
status: Final
|
||
type: Standards Track
|
||
category: ERC
|
||
created: 2019-10-08
|
||
requires: 721
|
||
---
|
||
|
||
## Simple Summary
|
||
|
||
A standardized event emitted when creating/transferring one, or many non-fungible tokens using consecutive token identifiers.
|
||
|
||
## Abstract
|
||
|
||
The optional ERC-721 Consecutive Transfer Extension provides a standardized event which could be emitted during the creation/transfer of one, or many non-fungible tokens. This standard does not set the expectation of how you might create/transfer many tokens it is only concerned with the event emitted after the creation, or transfer of ownership of these tokens. This extension assumes that token identifiers are in consecutive order.
|
||
|
||
## Motivation
|
||
|
||
This extension provides even more scalibility of the [ERC-721 specification](./eip-721.md). It is possible to create, transfer, and burn 2^256 non-fungible tokens in one transaction. However, it is not possible to emit that many `Transfer` events in one transaction. The `Transfer` event is part of the original specification which states:
|
||
|
||
> This emits when ownership of any NFT changes by any mechanism.
|
||
> This event emits when NFTs are created (`from` == 0) and destroyed
|
||
> (`to` == 0). Exception: during contract creation, any number of NFTs
|
||
> may be created and assigned without emitting Transfer. At the time of
|
||
> any transfer, the approved address for that NFT (if any) is reset to none.
|
||
|
||
This allows for the original `Transfer` event to be emitted for one token at a time, which in turn gives us O(n) time complexity. Minting one billion NFTs can be done in one transaction using efficient data structures, but in order to emit the `Transfer` event - according to the original spec - one would need a loop with one billion iterations which is bound to run out of gas, or exceed transaction timeout limits. This cannot be accomplished with the current spec. This extension solves that problem.
|
||
|
||
Many decentralized marketplaces and block explorers utilize the `Transfer` event as a way to determine which NFTs an address owns. The Consecutive Transfer Extension provides a standard mechanism for these platforms to use to determine ownership of many tokens.
|
||
|
||
## Specification
|
||
|
||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
|
||
NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
|
||
"OPTIONAL" in this document are to be interpreted as described in
|
||
RFC 2119.
|
||
|
||
**ERC-721 compliant contracts MAY implement this Consecutive Transfer Extension to provide a standard event to be emitted at the time of creation, burn, or transfer of one or many consecutive tokens**
|
||
|
||
The address executing the transaction **MUST** own all the tokens within the range of `fromTokenId` and `toTokenId`, or **MUST** be an approved operator to act on the owners behalf.
|
||
|
||
The `fromTokenId` and `toTokenId` **MUST** be a consecutive range of tokens IDs.
|
||
|
||
The `fromTokenId`, `fromAddress`, and `toAddress` **MUST** be indexed parameters
|
||
|
||
The `toTokenId` **MUST NOT** be an indexed parameter
|
||
|
||
When minting/creating tokens, the `fromAddress` argument **MUST** be set to `0x0` (i.e. zero address).
|
||
|
||
When burning/destroying tokens, the `toAddress` argument **MUST** be set to `0x0` (i.e. zero address).
|
||
|
||
When emitting the ConsecutiveTransfer event the Transfer event **MUST NOT** be emitted
|
||
|
||
Contracts that implement the `ConsecutiveTransfer` event **MAY** still use the original `Transfer` event, however when emitting the `ConsecutiveTransfer` event the `Transfer` event **MUST NOT** be emitted.
|
||
|
||
```solidity
|
||
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed fromAddress, address indexed toAddress);
|
||
```
|
||
|
||
### Examples
|
||
|
||
The `ConsecutiveTransfer` event can be used for a single token as well as many tokens:
|
||
|
||
**Single token creation**
|
||
|
||
`emit ConsecutiveTransfer(1, 1, address(0), toAddress);`
|
||
|
||
**Batch token creation**
|
||
|
||
`emit ConsecutiveTransfer(1, 100000, address(0), toAddress);`
|
||
|
||
**Batch token transfer**
|
||
|
||
`emit ConsecutiveTransfer(1, 100000, fromAddress, toAddress);`
|
||
|
||
**Burn**
|
||
|
||
`emit ConsecutiveTransfer(1, 100000, from, address(0));`
|
||
|
||
|
||
## Rationale
|
||
|
||
Standardizing the `ConsecutiveTransfer` event gives decentralized platforms a standard way of determining ownership of large quantities of non-fungible tokens without the need to support a new token standard. There are many ways in which the batch creation and transfer of NFTs can be implemented. The Consecutive Transfer Extension allows contract creators to implement batch creation, transfer, and burn methods however they see fit, but provides a standardized event in which all implementations can use. By specifying a range of consecutive token identifiers we can easily cover the transfer, or creation of 2^(256) tokens and decentralized platforms can react accordingly.
|
||
|
||
Take this example. I sell magical fruit and have a farm with 10,000 magical fruit trees each with different fruit and 1,000 new trees every few years. I want to turn each tree into a non-fungible token that people can own. Each person that owns one of my non-fungible tree tokens will receive a quarterly percentage of each harvest from that tree. The problem is that I would need to create and transfer each of these tokens individually - which will cost me a lot of time and money and frankly would keep me from doing this.
|
||
|
||
With this extension I would be able to to mint my initial 10,000 tree tokens in one transaction. I would be able to quickly and cheaply mint my additional 1,000 tree tokens when a new batch is planted. I would then be able to transfer all of the 10,000+ tree tokens to a special smart contract that keeps track of the selling and distribution of funds in one transaction all while adhering to a specified standard.
|
||
|
||
**Rationale to have a single event that covers minting, burning, and transferring**
|
||
|
||
The `ConsecutiveTransfer` event can be used to cover minting, burning, and transferring events. While there may have been confusion in the beginning adhering to transfer to/from "0" pattern this is mitigated by checking for the `ConsecutiveTransfer` topic and verifying the emitting contract supports the ERC-721 interface by using the ERC-165 standard.
|
||
|
||
**Indexed event parameters**
|
||
|
||
Events in Solidity can have up to three indexed parameters which will make it possible to filter for specific values of indexed arguments. This standard sets the `fromAddress`, `toAddress`, and `fromTokenId` as the indexed parameters. The `toTokenId` can be retrieved from the data part of the log. The reason for this is that more often than not one may be searching for events to learn about the history of ownership for a given address. The `fromTokenId` can then be retrieved along with the other two indexed parameters for simplicity. Then one only needs to decode the log data which is ensured to be the `toTokenId`.
|
||
|
||
**Rationale to not emit `Transfer` when `ConsecutiveTransfer` is also emitted**
|
||
|
||
This can lead to bugs and unnecessary complex logic for platforms using these events to track token ownership. When transferring a single token it is acceptable to emit the original `Transfer` event, but the `ConsecutiveTransfer` event should not be emitted during the same transaction and vice-versa.
|
||
|
||
**Comparing 2309 and 1155**
|
||
|
||
As the NFT market continues to grow so does the need for the ability to scale the smart contracts. Users need to be able to do things like mint a massive amount of tokens at one time, transfer a massive amount of tokens, and be able to track ownership of all these assets. We need to do this in a way that is cost effective and doesn’t fail under the confines of the Ethereum blockchain. As millions of tokens are minted we need contracts with the ability to scale.
|
||
|
||
[ERC-1155](./eip-1155.md) was created and added as a standard in 2019 to try to solve these problems, but it falls short when it comes to minting massive amounts of unique tokens in a cost-effective way. With ERC-1155 it’s either going to cost hundreds (or thousands) of dollars or it’s going to run out of gas. ERC-1155 works well when minting many semi-fungible tokens but falls short when minting many unique tokens. Using the 2309 standard you could mint millions of blank NFTs upfront and update the metadata for each one in a cost effective way.
|
||
|
||
|
||
## Backwards Compatibility
|
||
|
||
This extension was written to allow for the smallest change possible to the original ERC-721 spec while still providing a mechanism to track the creation, transfer, and deletion of a massive amount of tokens. While it is a minimal change the effects on platforms that only use the original `Transfer` event to index token ownership would be severe. They would not be properly recording token ownership information that could be known by listening for the `ConsecutiveTransfer` event. For platforms that wish to support the `ConsecutiveTransfer` event it would be best to support both the original `Transfer` event and the `ConsecutiveTransfer` event to track token ownership.
|
||
|
||
## Security Considerations
|
||
There are no security considerations related directly to the implementation of this standard.
|
||
|
||
## Copyright
|
||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md).
|