ERC-2309 ERC-721 Consecutive Transfer Extension

Final · NFTs & multi-token · created 2019-10-08

An ERC-721 extension standard that lets NFTs with consecutive token IDs be created, moved, or destroyed in bulk while emitting a single event covering one range, instead of emitting a notification for each token.

Why it is needed

ERC-721, the NFT standard, requires emitting one Transfer event each time token ownership changes. With efficient data structures, billions of NFTs can be created in a single transaction, but under the original specification this would require a loop of billions of iterations to emit that many Transfer events. Such a loop runs out of gas or exceeds the transaction limit and ultimately cannot be executed. Meanwhile, many decentralized marketplaces and block explorers watch Transfer events to determine which address holds which NFT. In other words, if tokens are minted in bulk without events, these platforms have no way to track ownership. This standard solves the problem by providing a common way to announce an entire range of consecutive token IDs with a single event.

What to implement

In depth

Event definition and indexed parameters

A single ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed fromAddress, address indexed toAddress) expresses creation, transfer, and burning. fromTokenId, fromAddress, and toAddress must be indexed parameters, and toTokenId must not be an indexed parameter. A Solidity event can have at most three indexed parameters. Because the common need is to look up the ownership history of a particular address, the two addresses and the starting ID are indexed, and toTokenId is obtained by decoding the data portion of the log.

Zero address rule for minting and burning

When creating tokens, fromAddress must be set to the zero address (0x0), and when burning, toAddress must be set to the zero address (MUST). For example, a single mint is written as emit ConsecutiveTransfer(1, 1, address(0), toAddress), a batch mint of 100,000 as emit ConsecutiveTransfer(1, 100000, address(0), toAddress), and a batch burn as emit ConsecutiveTransfer(1, 100000, from, address(0)). The confusion caused by merging minting, transfer, and burning into one event can be reduced by checking the ConsecutiveTransfer topic and verifying with ERC-165 that the contract supports the ERC-721 interface.

No duplication with the Transfer event

When emitting a ConsecutiveTransfer event, the original Transfer event must not be emitted for the same operation (MUST NOT). A contract implementing this standard may keep using the existing Transfer event for single-token transfers, but must not emit both events in the same transaction. If the two events overlap, platforms that track ownership through events get bugs and needlessly complex logic.

Requirements for the executor and the range

The address executing the transaction must own all tokens in the range from fromTokenId to toTokenId, or be an approved operator that can act on behalf of the owner (MUST). Also, fromTokenId and toTokenId must be a consecutive range of token IDs. This standard does not specify how batch creation, transfer, and burning are implemented, and standardizes only the event emitted afterward. The range approach can express transfers and creation of up to 2^256 tokens.

Comparison with ERC-1155

ERC-1155 also became a standard in 2019 to solve the bulk token problem, but according to the original text it falls short for minting unique tokens in bulk cheaply. ERC-1155 suits bulk minting of semi-fungible tokens, but minting unique tokens in bulk becomes very expensive or runs out of gas. The original text explains that with the 2309 standard, it is possible to mint millions of blank NFTs first and then update each token's metadata in a cost-efficient way.

Backwards compatibility and platform support

This extension barely changes the existing ERC-721 specification, but it has a large impact on platforms that index ownership using only the existing Transfer event. If they do not listen for the ConsecutiveTransfer event, they cannot record the ownership changes it contains. Platforms that want to support this event are best off tracking both the existing Transfer event and the ConsecutiveTransfer event. The original text states that there are no security considerations directly related to this standard itself.

Original ERC · ← ERCs