ERC-7160 NFT Multi-Metadata Extension (ERC-721 Multi-Metadata Extension)

Final · NFTs & multi-token · created 2023-06-09

An ERC-721 extension standard that lets a single NFT carry multiple metadata addresses (URIs) and pin one of them as the representative.

Why it is needed

The existing ERC-721 metadata extension (ERC721Metadata) allows only one metadata address per token. However, some use cases need multiple addresses: a single token that bundles several assets, a token that records its metadata edit history on-chain, a token that serves different images for different aspect ratios, or a token that holds a work created together by several artists. Without a standard, each project stores multiple metadata in its own way, and apps (dApps) and marketplaces have no common way to find out or display which addresses a token has. The pin and unpin feature, which lets an owner choose which of several metadata to show as the representative, also has to be implemented separately by each service, which makes wide support difficult.

What to implement

In depth

tokenURIs: a lookup function that returns three values at once

tokenURIs(uint256 tokenId) returns (uint256 index, string[] memory uris, bool pinned). uris is the array of all URIs linked to the token, index is the array index of the pinned URI (or the index of the default URI if nothing is pinned), and pinned indicates whether a URI is pinned. It must revert if the token does not exist. The Rationale explains that a design that returns only a string array was considered, but additional information is returned together to reduce three calls to one.

pin and unpin: state changes that require events

pinTokenURI(tokenId, index) pins the URI at position index in the tokenURIs array and MUST emit the TokenUriPinned event when called. unpinTokenURI(tokenId) releases the pin and MUST emit the TokenUriUnpinned event. Both functions must revert if the token does not exist, and they MAY additionally emit the ERC-4906 MetadataUpdate event. The specific behavior after release is intentionally left for developers to decide. The reference implementation restricts both functions so that only the token owner can call them.

Backward compatibility with the existing tokenURI

The tokenURI function of the ERC-721 metadata extension MUST return the pinned URI if the token has one, and MUST return the default URI if nothing is pinned. Thanks to this rule, existing apps that know nothing about ERC-7160 receive the correct representative metadata by calling only tokenURI. The reference implementation uses the last item of the array (length - 1) as the default URI when nothing is pinned.

Interface identifier and ERC-165

The ERC-165 identifier of this interface is 0x06e1bc5b. A call to supportsInterface(0x06e1bc5b) MUST return true. With this check, an app can know in advance whether a contract supports multi-metadata.

Adding and removing URIs is outside the standard, ERC-4906 recommended alongside

The feature for adding or removing URIs on a token MUST be implemented separately from this standard. When adding or removing, emitting the events defined in ERC-4906 is RECOMMENDED. The Rationale explains that many apps already support ERC-4906 events, that they fit the purpose of notifying that metadata has changed, and that using them avoids app problems caused by duplicate events. A party that receives the event can call tokenURIs to fetch the updated list.

Event-based indexing and use cases

By subscribing to the TokenUriPinned and TokenUriUnpinned events, an app can index which metadata to display on an event basis, without on-chain calls. Use cases cited in the source text include rotating asset collections, on-chain records of metadata edit history, metadata per aspect ratio, dynamically evolving metadata, and joint tokens by multiple artists. The pinned URI can be used as the token's representative, and the rest of the list can be shown as a gallery or media carousel.

Things to watch out for

Original ERC · ← ERCs