ERC-1046 tokenURI interoperability extension (tokenURI Interoperability)

Final · Names & metadata · created 2018-04-13

Adds a tokenURI() function to ERC-20 tokens, returning an address with an image and description as ERC-721 does, and adds an interop field to ERC-20, ERC-721 and ERC-1155 metadata that states the token type, so that wallets read all three standards the same way.

Why it is needed

ERC-721 non-fungible tokens (NFTs) have a tokenURI function that returns an address holding extra information such as a thumbnail image, a title and a description. ERC-20 tokens, however, have no standard function that does the same job, so there was no defined way to find where to get a token logo or description. It was also hard for a wallet or website that met a contract to tell from the metadata alone whether it was ERC-20, ERC-721 or ERC-1155, and what features the token had. The ERC-165 approach of querying the contract directly can be used to find the type, but the original explains that such static calls are time-consuming and inflexible for wallets and websites. This standard solves the problem by adding tokenURI to ERC-20 and adding an interop field that states the token type to the metadata JSON of all three standards.

What to implement

In depth

Interoperability metadata (InteroperabilityMetadata)

The shape of the interop object that is common to the metadata JSON of all three standards. It has three fields, erc1046, erc721 and erc1155, and every field must be optional. Each field must be set to true when the metadata belongs to the corresponding standard and must be omitted otherwise. If erc1046 is true, the wallet should treat the address as an ERC-20 token, if erc721 is true as an ERC-721 token, and if erc1155 is true as an ERC-1155 token. Other proposals can extend this interface. Not every field needs to be a boolean, so any optional object that can be serialized as JSON can be used as an extension field.

ERC-20 interface extension: tokenURI()

An ERC-20 contract that follows this standard must implement the ERC20TokenMetadata interface. The interface has only one function, tokenURI(), which is called with no arguments and is external view returning a string. The data that the returned URI points to must be in JSON format and must support the ERC-20 Token Metadata Schema of this standard. Unlike tokenURI(uint256) in ERC-721, it has no token ID argument. The original gives easier code reuse as the reason for using the same name as ERC-721.

ERC-20 token metadata schema

The JSON that tokenURI() points to must follow the ERC20TokenMetadata interface. interop is required and the rest are optional. If the contract has name() and symbol() functions that return non-empty values, name and symbol must be the same values. decimals must also be the same value if a decimals() function exists, and if both the field and the function are absent the default is 18. description is a short one-paragraph description with no markup and no line breaks. image is a single URI pointing to a resource whose mime type is image/*, and images is an array of URIs of the same kind. For bitmaps, a width of 320 to 1080 pixels and an aspect ratio between 1.91:1 and 4:5 are recommended. icons is an array of URIs for icons. For bitmaps, a width of 320 to 1080 pixels is recommended, the height must equal the width, and a 1:1 ratio with a transparent background must be used.

ERC-721 extension

A contract that implements ERC-721 and uses a token metadata URI SHOULD use the ERC721TokenMetadataInterop form, which extends the existing ERC721TokenMetadata. The only addition is the interop field, which is meant to avoid confusion between different token URIs. The ERC-721 extension in the original covers only the metadata schema and adds no new Solidity function. It is enough to add interop to the JSON that the existing tokenURI(tokenId) points to.

ERC-1155 extension: tokenURI(tokenId) and schema

An ERC-1155 contract that uses the metadata extension SHOULD implement the ERC1155TokenMetadataInterop interface. The tokenURI(uint256 tokenId) function of this interface takes a token ID and returns a string, the data it points to must be JSON, and it must support the ERC-1155 schema extension of this standard. If the contract has a uri(tokenId) function, tokenURI(tokenId) must return the same URI. On the metadata side, the ERC1155TokenMetadataInterop form, which extends ERC1155TokenMetadata and adds the interop field, is RECOMMENDED. However, a contract that implements the Solidity interface above must use this extended form.

Gas saving recommendation: omit name, symbol and decimals

To save gas, a contract that follows this standard is recommended not to implement the name(), symbol() and decimals() functions and to put those values only in the metadata URI. If an ERC-20 token has decimals of 18, it is NOT RECOMMENDED to include a decimals field in the metadata. Because the default is 18 when both the decimals field and the decimals() function are absent in the schema, a wallet interprets decimals as 18 even if both are omitted. However, if the function is implemented, the rule that it must match the metadata value still applies.

Rationale and backwards compatibility

The original explains that using the same tokenURI name as ERC-721 makes it easy for developers to attach metadata to ERC-20, makes code easy to reuse, and has almost no effect on the ecosystem. The token type can also be determined with ERC-165, but a static call is time-consuming and inflexible for wallets and websites. Putting interoperability information inside the token URI instead improves both flexibility and performance. Because this standard is an optional extension of ERC-20 functionality, it is fully backwards compatible, and the recommendations for ERC-721 and ERC-1155 are also backwards compatible. The status in the original is Final.

Things to watch out for

Original ERC · ← ERCs