ERC-5007 Time NFT: ERC-721 Time Extension (Time NFT, ERC-721 Time Extension)
Final · NFTs & multi-token · created 2022-04-13
An extension that adds startTime and endTime query functions to ERC-721 NFTs so that a token's validity period can be managed on chain in a standard way.
Why it is needed
Some NFTs have a set usage period and cannot be used outside it. However, the existing ERC-721 has no time information, so invalidating or activating a token at a specific point in time requires someone to send a transaction manually. This process is cumbersome and costs fees. Some NFTs have built in their own time features, but each contract has a different interface, so third-party platforms such as wallets and marketplaces find it hard to support them in a common way. This standard defines two common functions that query the start time and end time, so NFTs can be switched on and off automatically on chain without sending a separate transaction.
What to implement
function startTime(uint256 tokenId) external view returns (uint64);: Returns the start time of the NFT as a UNIX timestamp. The tokenId must exist.function endTime(uint256 tokenId) external view returns (uint64);: Returns the end time of the NFT as a UNIX timestamp. The tokenId must exist.function assetId(uint256 tokenId) external view returns (uint256);: Returns the asset ID of the time NFT. Only NFTs with the same asset ID can be merged.
In depth
Base interface IERC5007
Two query functions are the core. startTime(uint256 tokenId) returns the start time of the NFT and endTime(uint256 tokenId) returns the end time, both as UNIX timestamps, and the return type of both is uint64. Both functions require that the tokenId exist. The ERC-165 identifier of this interface is 0xf140be0d, so an external platform can check through an ERC-165 query which contracts support this extension. There are no state-changing functions and the interface is read-only, so the decision on whether a token is active or inactive at a given time is made by whoever reads these values.
Optional extension IERC5007Composable
The composable extension is OPTIONAL in this standard. It lets you issue new NFTs from an existing NFT to split it, or combine two NFTs into one. assetId(uint256 tokenId) returns the asset ID of the time NFT, and only NFTs with the same asset ID can be merged. The ERC-165 identifier of this interface is 0x75cf3842. The assetId of a new token created by a split is the same as the assetId of the original token.
Requirements of split
split divides one existing token (oldTokenId) into two new tokens. oldTokenId must exist, newToken1Id and newToken2Id must not exist yet, and newToken1Owner and newToken2Owner cannot be the zero address. The split reference time, splitTime, is subject to the condition require(oldToken.startTime <= splitTime && splitTime < oldToken.EndTime), so it must fall within the validity period of the original token. In other words, one period can be cut into two periods before and after splitTime and given to different owners.
Requirements of merge
merge combines the first token and the second token into one new token. firstTokenId and secondTokenId must both exist, and under the condition require((firstToken.endTime + 1) == secondToken.startTime), the second token's start time must come immediately after the first token's end time. Also, require((firstToken.assetId()) == secondToken.assetId()) requires that the two tokens have the same asset ID. newTokenOwner cannot be the zero address and newTokenId must not exist yet. In effect, only two pieces of the same asset that connect without a time gap can be joined back into one.
Why uint64 is used for time values
The maximum value of uint64 is 18,446,744,073,709,551,615, which as a timestamp corresponds to about 584,942,419,325 years, enough to represent time. In contrast, uint256 is too large to handle in languages such as C, C++, Java, and Go, while uint64 is supported by default in major programming languages. So uint64 is used for the return types of startTime and endTime and for the splitTime parameter of split.
Compatibility and implementation resources
This standard is fully compatible with ERC-721, because it adds query functions without changing existing ERC-721 behavior. The original text provides test cases run with truffle (test.js) and a reference implementation (ERC5007.sol). The standard itself requires ERC-165 and ERC-721 (requires: 165, 721), and its status is Final, meaning it is a settled standard.