ERC-6672 Multi-exchangeable NFT (Multi-redeemable NFTs)
Final · NFTs & multi-token · created 2023-02-21
An ERC-721 extension standard that lets a single NFT be redeemed multiple times across different scenarios for physical goods or digital benefits, with each redemption recorded on the blockchain.
Why it is needed
NFT redemption is the act in which a holder proves ownership and eligibility and receives a physical or digital item in return. Until now, an NFT could be redeemed only once, which made it hard to reuse the same NFT across several events or campaigns. A digital concert ticket NFT, for example, should be able to carry a different experience and benefit with each redemption: once for entry to an online show, again for collecting limited-edition merchandise, and again for a meeting with the artist. There is also a need to check on chain which NFT has already been redeemed in which operator's campaign. This standard enables such multiple redemptions through a record structure that combines the operator, the token, and the redemption.
What to implement
function isRedeemed(address _operator, bytes32 _redemptionId, uint256 _tokenId) external view returns (bool);: Returns whether the NFT has already been redeemed in a specific redemption of a specific operator.function getRedemptionIds(address _operator, uint256 _tokenId) external view returns (bytes32[]);: Returns the list of identifiers of redemptions that the operator created for the NFT.function redeem(bytes32 _redemptionId, uint256 _tokenId, string _memo) external;: Redeems the NFT. The caller (msg.sender) is recorded as the operator of that redemption.function cancel(bytes32 _redemptionId, uint256 _tokenId, string _memo) external;: Cancels a redemption. Only the operator that created the redemption can call it.function tokenURI(uint256 _tokenId) external view returns (string);: A function of the optional metadata extension that returns the location (URI) of the token's metadata JSON.
In depth
Operator authority and the msg.sender rule
An operator SHALL be able to modify only the redemption records it created. To enforce this, the redeem() and cancel() functions have no _operator parameter and MUST use the caller address, msg.sender, as the _operator. In other words, no other address can redeem or cancel on behalf of a redemption created by a given operator.
Key structure of the redemption flag
Whether a redemption has occurred is stored as a key-value pair. The key MUST be the combination of the three values _operator, _tokenId, and _redemptionId. The value is read with the isRedeemed() function. Each of the three values is needed for a different reason. The operator address is needed because the same NFT can be used for redemption by several parties (for example, a MisterPunks NFT redeemed for Event-X and Event-Y tickets run by different operators). The token identifier is needed because the records an operator creates differ from holder to holder. The redemption identifier is needed so that the same NFT can be redeemed in several campaigns of the same operator (for example, MisterPunk #7 redeemed for a figure in each of Operator-X's campaigns A and B).
Required interfaces and identifier
A contract that follows this standard MUST implement both the ERC6672 and ERC721 interfaces. The ERC-165 identifier of the IERC6672 interface is 0x4dddf83f. The interface consists of the Redeem and Cancel events, the query functions isRedeemed() and getRedemptionIds(), and the execution functions redeem() and cancel(). This standard is compatible with ERC-721.
Optional metadata extension
IERC6672Metadata is OPTIONAL. tokenURI(uint256 _tokenId) can point to a JSON file that follows the ERC-6672 metadata JSON schema. It throws an exception for an invalid token. Besides the basic name, description, and image, the schema has a redemptions entry, whose keys MUST be standardized in the operator-tokenId-redemptionId format. The value of each key is an object containing status and description.
The status and description fields
The redemption status in the metadata can be more granular than a simple true/false flag. For a physical goods redemption, stages such as redeemed, paid, and shipping may be needed. Using a string enumeration (enum) that everyone who displays the status, including operators and marketplaces, can understand is RECOMMENDED. The description SHOULD be used to provide details of the redemption, such as concert ticket information or a detailed description of a figure.
Things to watch out for
- Authority isolation between operators: If implemented incorrectly, an unauthorized operator could access another operator's redemption flag and cancel someone else's redemption process. The implementation must ensure that only the operator that created the redemption, identified by msg.sender, can change the redemption flag through redeem() and cancel().
- Separation from the ERC-721 approval model: It is RECOMMENDED to isolate the redeem() and cancel() functions from the ERC-721 approval model. Because this token is compatible with ERC-721, wallets and contracts that can handle standard ERC-721 tokens run no risk of asset loss from an incompatible implementation.