-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add EIP: Versioned TokenIDs for Dynamic NFTs #6912
Closed
+124
−0
Closed
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
f1940d9
add versioned token ID EIP
emo-eth 52b444c
update with number
emo-eth 103c094
address validation errors
emo-eth 8f0be76
merge summary and abstract
emo-eth eab9eb3
remove ens
emo-eth 08958dc
link 721
emo-eth 1770975
blank lines for headings
emo-eth 5b36079
add getEncodedTokenIdentifier
jameswenzel 9ddb91b
update interface and add 165 requirement
jameswenzel d6c9e63
walidator tweaks
jameswenzel ba0e634
more tweaks
jameswenzel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
--- | ||
eip: 6912 | ||
title: Versioned TokenIDs for Dynamic NFTs | ||
description: A minimal, backwards-compatible specification for versioned token IDs for dynamic NFTs. | ||
author: James Wenzel (@jameswenzel) | ||
discussions-to: https://ethereum-magicians.org/t/eip-6912-versioned-tokenids-for-dynamic-nfts/13897 | ||
status: Draft | ||
type: Standards Track | ||
category: ERC | ||
created: 2023-04-19 | ||
requires: 165, 721 | ||
--- | ||
|
||
## Abstract | ||
|
||
This EIP proposes an extension to the [ERC-721](./eip-721.md) non-fungible token standard by introducing a Versioned TokenId standard for "dynamic" NFTs with on or offchain properties that may change over time. The new "versioned tokenId" is meant to track both the "identifier" of a token as well as its current "version number" so that old outstanding orders and approvals for updated tokens are automatically invalidated. | ||
|
||
A `uint256 versionedTokenId` MUST encode both the true token "identifier" along with a "version number". Encoding, storage, and retrieval specific details should be left up to individual token implementations, and this EIP does not make specific recommendations. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You shouldn't introduce any requirements ("MUST") outside of the Specification section. Give an overview in the abstract, but don't use the RFC 2119 keywords. |
||
|
||
When any onchain action occurs that changes a dynamic token's metadata (on or offchain), the token contract MUST emit a transfer event for the current `versionedTokenId` from the current owner to the null address (i.e., "burning" the old token). It also then MUST emit a transfer event of an updated `versionedTokenId` (which encodes the new "version number" and the same "identifier") from the null address to the original owner. The actual encoded token "identifier" MUST not change, and the encoded "version number" MUST change. | ||
|
||
## Motivation | ||
|
||
The primary motivation for this EIP is to prevent unintentional sales or approved transfers of tokens whose metadata has been updated, while maintaining backward compatibility with all known marketplaces. | ||
|
||
Currently, if a token has a metadata update that makes it subjectively more or less valuable, all open orders, bids, and asks will still be valid. This standard aims to prevent malicious or unintended sales and previously approved transfers of NFTs after they have been changed on or offchain. By implementing this EIP, developers can create NFTs that automatically update their `versionedTokenId` when metadata changes occur, which will invalidate open orders and ensure that only the latest version of a token is used in onchain transactions. | ||
|
||
## Specification | ||
|
||
**Smart contracts implementing the [ERC-6912](./eip-6912.md) standard MUST implement all methods in the `IERC6912` interface.** | ||
|
||
**Smart contracts implementing the ERC-6912 standard MUST implement the [ERC-165](./eip-165.md) `supportsInterface` method and MUST return the constant value `true` if `0xe98e3e5e` is passed through the interfaceID argument.** | ||
|
||
### Interface | ||
|
||
```solidity | ||
/** | ||
* @title ERC6912 Versioned TokenIDs for Dynamic NFTs | ||
* @dev See https://eips.ethereum.org/EIPS/eip-6912 | ||
* Note: The ERC-165 identifier for this interface is 0xe98e3e5e. | ||
*/ | ||
interface IERC6912 /* is ERC165 */ { | ||
|
||
/** | ||
* @notice This method is meant to ensure that it is always possible to find the current valid `cversionedTokenid` for a given | ||
* token, even with an out-of-date or otherwise incorrect `versionedTokenId`, so long as the encoded "identifier" is valid. | ||
* MUST return the current `versionedTokenId` for the "identifier" encoded by a given `tokenId`. | ||
* MUST revert if passed a `tokenId` with an invalid or non-existent "identifier." | ||
* MUST return the current "version number" for the "identifier" encoded by the `tokenId`. | ||
* MUST NOT revert if the encoded "version number" is incorrect or outdated. | ||
* Implementation details about storage and retrieval of versioned token IDs SHOULD be left up to individual implementations. | ||
*/ | ||
function getCurrentVersionedTokenId(uint256 tokenId) external view returns (uint256); | ||
|
||
/** | ||
* @notice This method is meant to ensure it is always possible to find the encoded "identifier" for a given `versionedTokenId`, | ||
* even with an out-of-date or otherwise incorrect `versionedTokenId`. | ||
* MUST return the encoded "identifier" for a given `versionedTokenId`. | ||
* MUST NOT revert if the encoded "version number" is incorrect or outdated. | ||
* MAY revert if no token exists for the encoded "identifier" or the "identifier" is otherwise invalid. | ||
*/ | ||
function getEncodedTokenIdentifier(uint256 versionedTokenId) external view returns (uint256); | ||
|
||
} | ||
``` | ||
|
||
### Changes to ERC-721 Events | ||
|
||
#### `event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);` | ||
|
||
The standard ERC-721 `Transfer` event MUST be emitted when a token's metadata changes, first for the current `versionedTokenId` (including its encoded "token version") from the current owner to the null address, then for the updated `versionedTokenId` (which encodes the new "token version" and the same "identifier") from the null address to the original owner. This is equivalent to a "burn" event for the old `versionedTokenId`, followed by a "mint" event for the new `versionedTokenId`. | ||
|
||
|
||
### Changes to ERC-721 Methods | ||
|
||
The following methods from ERC-721 MUST be updated to handle `versionedTokenIds`: | ||
|
||
```solidity | ||
function approve(address, uint256) external; | ||
|
||
function getApproved(uint256) external returns (address) external view; | ||
|
||
function transferFrom(address, address, uint256) external; | ||
|
||
function safeTransferFrom(address, address, uint256) external; | ||
|
||
function safeTransferFrom(address, address, uint256, bytes) external; | ||
|
||
function tokenURI(uint256) external view returns (string); // from the optional ERC721Metadata extension | ||
``` | ||
|
||
Each method MUST revert when called with a `versionedTokenId` that encodes an incorrect or outdated "version number". | ||
|
||
Each method SHOULD behave normally when called with a `versionedTokenId` that encodes the current "version number" for a valid "identifier." | ||
|
||
```solidity | ||
function ownerOf(uint256) external returns (address) external view; | ||
``` | ||
|
||
The `ownerOf` method MUST return the current owner of the token with the given `versionedTokenId` if the encoded "version number" is current or `0`. If the `versionedTokenId` encodes an incorrect or outdated (non-zero) "version number", the method MUST revert. | ||
|
||
For compatibility with onchain protocols that assume a 1-to-1 mapping of a `tokenId` to a conceptual "identifier" (such as [ERC-6551](./eip-6551.md)), the `ownerOf` method MAY revert for any `versionedTokenId` that encodes a non-zero "version number," only when called by a specific caller or set of callers (such as the ERC-6551 registry contract) to be determined by the implementer. | ||
|
||
|
||
## Rationale | ||
|
||
The introduction of versioned token IDs allows for better and safer marketplace handling of NFTs with changing metadata, and ensures that only the latest "version number" of a token is used in onchain transactions. All indexers that track token burns and mints should be compatible with ERC-6912 tokens. The specified behavior in this EIP minimizes the changes to the ERC-721 standard while maintaining full backwards-compatibility with all known marketplaces. | ||
|
||
## Backwards Compatibility | ||
|
||
This EIP aims to be fully backwards-compatible with ERC-721 and ERC-721-compatible marketplaces. | ||
|
||
To maintain compatibility with onchain protocols that rely on constant `tokenId`s, implementers may refer to the optional behavior described for the `ownerOf` method. | ||
|
||
## Security Considerations | ||
|
||
Since some NFT marketplaces allow for bulk-signing of up to millions of orders, token developers who anticipate many metadata updates for their token SHOULD make individual token "version numbers" non-incremental but monotonically increasing. They SHOULD use a method of deriving new "version numbers" that makes it difficult or impossible to anticipate future `versionedTokenIds` far in advance, in order to make bulk signature phishing impractical. | ||
|
||
As an example, one method would be to use the current BLOCKHASH or PREVRANDAO to increment the current version number, truncated to the desired number of bits. While BLOCKHASH and PREVRANDAO are deterministic and able to be influenced, they are impractical to predict indefinitely far in advance, and are not easily influenced by a single actor. | ||
|
||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your description doesn't really add any information over the title. Answering the question of "what is a versioned token ID" would be a reasonable goal for your description.