ERC-6220 Equippable Composable Parts NFT (Composable NFTs utilizing Equippable Parts)

Final · NFTs & multi-token · created 2022-12-20

An ERC-721 extension standard that lets an NFT select and combine parts predefined in a catalog, and equip or unequip other NFTs in slots. Equipping does not create a new token, and the equipped items are rendered together when the token is queried.

Why it is needed

Previously, combining several NFTs into one composite required either gathering all compatible NFTs in an account and using them indiscriminately, or building a separate ledger in a smart contract or an off-chain database. When more than one NFT was eligible for the same slot, it was also unpredictable which one would be applied. In addition, when a game character grew and obtained items, each item had to be carried around as a separate NFT, and a central operator had to manage the equipped state. Scarcity was a problem as well. The same hat NFT could be worn by 500 avatars in 500 game instances at the same time, because the visual representation was only client-side processing. This standard creates a framework in which a single NFT directly chooses which parts to use as part of the whole and keeps that information on-chain, providing predictable composition and real digital scarcity.

What to implement

In depth

Two kinds of parts: fixed and slot

A Fixed part is a complete component with its own metadata. It does not change during the NFT's lifetime and cannot be replaced. Once defined, it can be equipped by many tokens across many collections, which distributes recurring assets efficiently. A Slot part has no metadata of its own and allows a selected NFT collection to be equipped into it. Because the equipped token supplies its own metadata, it becomes swappable content controlled by the owner. You do not need to use both kinds, and you can apply only the configuration you need.

Catalog structure and the Part struct

A catalog is a collection of fixed and slot parts, and it is not tied to a single collection, so it can support multiple NFT collections. The Part struct consists of itemType (None, Slot, Fixed), z (uint8) which sets the rendering depth, equippable, an array of addresses allowed to equip, and metadataURI. Parts are added by specifying partId through IntakeStruct, and using a partId that is already in use reverts the addition. One catalog entry needs at least 3 storage slots (about 60,000 gas as of the Berlin hard fork), and considering the length of an IPFS URI, 5 to 7 slots is realistic. It costs 25,000,000 to 35,000,000 gas per 250 assets, while the maximum block size on mainnet is 30M.

equip, unequip, and the Equipment storage structure

equip takes an IntakeEquip struct (tokenId, childIndex, assetId, slotPartId, childAssetId) as input. Equipping does not create a new token. It only adds a component that will be rendered together when the token is queried. unequip can be called only by the token owner or an account the owner has granted management permission. The equipped state is stored as an Equipment struct (assetId, childAssetId, childId, childEquippableAddress) and is queried per slot with getEquipment. Each action is announced with the ChildAssetEquipped and ChildAssetUnequipped events.

Equip permission verification system

What can be equipped where is verified at several layers. On the catalog side, checkIsEquippable(partId, targetAddress) checks whether a specific collection can be equipped to a part, and checkIsEquippableToAll(partId) checks whether a part is open to all addresses. On the token side, an asset belongs to an equip group called equippableGroupId, and as the ValidParentEquippableGroupIdSet event announces, whether a group can be equipped is specified per group for a specific slot of a specific parent collection. canTokenBeEquippedWithAssetIntoSlot lets you query whether equipping is possible before you equip. If NFTs were equipped directly without any oversight, the resulting combinations would be unpredictable, so the design intent is to verify parts in advance through the catalog so that they combine as intended.

Provable digital scarcity

With existing NFTs, supply was limited but usage was not. With the same wallet and the same NFT, you can join 500 game instances and put the same hat on 500 avatars at once, because the visual representation is only client-side processing. This standard enforces that once a hat is equipped to one avatar (equipped after being transferred into the avatar token), it cannot be equipped to another avatar. isChildEquipped is used to block transfer of an equipped child, which supports this guarantee.

Dependent standards and compatibility

This standard requires ERC-165, ERC-721, ERC-5773, and ERC-6059. The IERC6220 interface inherits IERC5773, its ERC-165 identifier is 0x28bc9ae4, and the identifier of ICatalog is 0xd912401f. It is designed to be compatible with ERC-721, so existing ERC-721 tools and infrastructure can be used as is. A method that fetches all equipped parts at once was not included because not every implementer needs it, and it can be added through an extension or hook, or replaced by an indexer. Its status is Final, a finalized standard.

Things to watch out for

Original ERC · ← ERCs