ERC-5773 Context-Dependent Multi-Asset Token (Context-Dependent Multi-Asset Tokens)

Final · NFTs & multi-token · created 2022-10-10

A standard that attaches multiple assets (files and data) to one NFT, so that the appropriate asset can be shown depending on the environment that opens it, such as an e-book reader, a game, or a marketplace.

Why it is needed

An existing ERC-721 NFT usually points to just one metadata address (tokenURI), so it is hard for the same token to carry different representations suited to different environments. To change the content, the issuer has to replace the whole URI, which makes earlier records hard to trace and lets the content change without the owner's consent, creating a trust problem. If the metadata sits only on one server or one particular IPFS gateway, the information can be lost when that host goes down. A game item NFT cannot be used in other games because their formats differ, and if the game server shuts down, the owner is left with a useless token. To reflect changes such as leveling up, the metadata had to be changed centrally or a new NFT had to be sent to the wallet. This standard solves these problems by holding multiple assets in one NFT, with additions and replacements proposed by the issuer and accepted by the owner.

What to implement

In depth

Two-array structure: active and pending

Each token's assets are managed in two arrays. The active array is the list of assets the owner has accepted and that are actually in use, and the pending array is the list of assets that have been proposed but not yet accepted. No one can delete an active asset; it can only be replaced with a new asset. To prevent spam and griefing, it is RECOMMENDED (SHOULD) that the pending array be limited to 128 slots. The owner MAY remove assets from both active and pending, and an emergency function that clears the entire pending array MUST be included.

Propose-commit pattern

When adding an asset to an already existing token, the propose-commit pattern MUST be followed. The asset first enters the pending array and moves to the active array only when the owner accepts it with acceptAsset. When a proposal that specifies a replacement target is accepted, the old asset is swapped for the new one, and the old asset remains reachable and verifiable, so traceability is preserved. Unlike a scheme where the issuer changes the URI arbitrarily, the asset does not change without the owner's consent, so owners can trust it more. Leveling up or firmware updates on IoT devices can be expressed through this replacement mechanism.

Double-checking index and assetId

acceptAsset and rejectAsset take an array index instead of an asset ID. Looking up by ID requires iterating over the array, so the cost grows with the array size, whereas using an index keeps the cost fixed. However, to prevent a race in which the index changes in the meantime, they also take the expected assetId and verify that the asset at that position is the right one. An implementation that tracks indexes internally with a mapping was also tried, but it was not adopted because it raised the cost of adding an asset by more than 25% and the costs of accepting and rejecting by 4.6% and 7.1% respectively. If needed, it can be implemented as an extension using hooks.

Priority array

setPriority sets a priority for each active asset. The priority array is a list of non-sequential values, and the lowest value has the highest priority. The value 0 is a special case equivalent to uninitialized. The length of the priorities array must equal the length of the active asset array, and the order of the array pairs with the order of the active array. The caller must be the token owner or an account approved for asset management, and an AssetPrioritySet event is emitted on the call. Consumers refer to these priorities to decide which asset to show first.

Asset approval separate from transfer approval

approveForAssets is an approval dedicated to asset management, separate from the transfer approval in ERC-721. When the approved account accepts or rejects assets or sets their priority, the approval is not cleared; it is cleared when the token is transferred. Only one account can be approved at a time, so approving the 0x0 address clears the existing approval. An operator designated through setApprovalForAllForAssets can call acceptAsset, rejectAsset, rejectAllAssets and setPriority on all tokens owned by the caller, and the operator cannot be the caller itself.

Reference-based storage structure

Assets are stored inside a token as an array of uint64 identifiers. To avoid storing duplicate strings on chain repeatedly, asset data is kept once in internal storage and referenced through a uint64 mapping. Even if the same universal asset is attached to many tokens, each token only needs 16 more bytes written to its asset array. Implementers can build a URI that varies with tokenId programmatically by concatenating the asset's base address and the token ID as strings. Because asset IDs are uint64, it was confirmed that about 30,000 can be read within the gas limit, so pagination was not included in the interface.

Asset metadata format

getAssetMetadata returns the asset's metadata URI. The metadata that URI points to MAY be JSON containing the fields name, description, mediaUri, thumbnailUri, externalUri, license, licenseUri, tags, preferThumb and attributes. preferThumb is a flag telling the UI to prefer thumbnailUri over mediaUri, and each entry in attributes may also include a trait_type field for backward compatibility. This schema is only a proposal and is not enforced, so implementers may structure it completely differently.

ERC-721 compatibility and interface identifier

This standard is designed to be compatible with ERC-721 so that the rich tooling and existing infrastructure of ERC-721 can be used as is. It requires ERC-165, and the ERC-165 identifier of this interface is 0x06b4329a. EIP-712 signatures are not used for approvals for the sake of consistency: ERC-721 already handles approvals with a single transaction, so mixing a signature scheme into only the asset operations was judged inconsistent. This standard is a proposal whose status is finalized as Final.

Things to watch out for

Original ERC · ← ERCs