{"id":"ERC-5007","name":"Time NFT Extension","status":"Final","chain":"both","category":{"id":"nft","name":"NFT Capabilities","description":"What NFTs can do beyond basic ownership"},"journeyStages":[{"id":"management","name":"Asset Management","description":"Managing assets over time"}],"uxImpact":"ERC-5007 adds start and end timestamp fields to NFTs. Consuming contracts can use those fields for subscriptions, season passes, or time-limited memberships; enforcement, boundary rules, and renewal remain implementation-specific.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-5007","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-5007","summary":"ERC-5007 adds start and end timestamp fields to NFTs. Consuming contracts can use those fields for subscriptions, season passes, or time-limited memberships; enforcement, boundary rules, and renewal remain implementation-specific.","applicability":{"whenToUse":["Your product needs a standardized on-chain validity window that a consuming contract or app can check.","Your product addresses: expired access tokens still appear in wallets.","The flow should deliver: NFT has on-chain startTime/endTime data that a consuming contract can check directly.","You are designing a subscription card experience with visible states and recovery paths."],"whenToAvoid":["The target token or consuming app does not support the required validity window.","Your flow needs automatic access revocation or renewal that the implementation does not provide.","You cannot determine how the consuming app applies the start and end boundaries."]},"designerTakeaways":["You can design UI that displays the on-chain startTime/endTime values and the consuming app's validity rule.","You can show \"Valid until Dec 31\" or \"Expired\" after checking the target implementation's boundary policy.","You can display a future start date when the minting or issuance implementation supports it."],"problemsSolved":[{"problem":"Validity windows lack a shared query interface","oldWay":"Products use custom contract fields or backend conventions that consumers must integrate separately","newWay":"NFT exposes on-chain startTime/endTime data that a consuming contract can check directly","impact":"critical"},{"problem":"Expired access tokens still appear in wallets","oldWay":"User sees membership NFT but it's actually expired","newWay":"UI can show the timestamp data and an implementation-specific active or expired state clearly","impact":"high"},{"problem":"Future activation dates are hard to discover consistently","oldWay":"A product can implement future activation, but other clients need its custom field or backend convention","newWay":"Represent future access when the issuance implementation sets a future startTime","impact":"high"}],"uxPatterns":[{"name":"Subscription Card","description":"Display time-limited NFT with validity period","userFlow":["User views their membership NFT","Sees validity period and time remaining","Progress bar shows how much time used","Can renew before expiration if the target implementation exposes a renewal path","After expiry, card shows \"Expired\" status"]},{"name":"Season Pass Timeline","description":"Show season pass with start and end dates","userFlow":["User purchases season pass","Sees exact start and end dates","Timeline shows current position","Tracks progress toward rewards","Consumer applies its configured expiry rule at season end"]},{"name":"Future Access Pre-Sale","description":"Sell access that starts in the future","userFlow":["User sees pre-sale for future access","Pass has startTime in the future","User reviews the issuer’s actual price and terms before purchase","NFT minted but not yet active","Consumer applies its configured startTime rule"]},{"name":"Expired Token Display","description":"Clear indication when time-limited NFT has expired","userFlow":["User views expired NFT","Card clearly shown as expired (grayed out)","Shows when it expired","Option to hide or follow an implementation-specific renewal path","Renewal changes validity only when the target implementation authorizes it"]}],"uiComponents":[{"name":"ValidityPeriodDisplay","description":"Show start and end time of NFT","states":["not-started","active","expiring-soon","expired"],"props":["startTime","endTime","showProgress"]},{"name":"ExpiryCountdown","description":"Countdown to expiration","states":["plenty-time","warning","critical","expired"],"props":["endTime","warningThreshold","criticalThreshold"]},{"name":"TimelineBadge","description":"Visual timeline showing validity period","states":["past","present","future"],"props":["startTime","endTime","currentTime"]},{"name":"RenewalPrompt","description":"Offer a renewal or reissue prompt only when the issuer provides a verified path; ERC-5007 has no renewal method.","states":["unsupported","hidden","suggested","urgent"],"props":["renewalSupported","daysUntilExpiry","renewalPrice","onRenew"]},{"name":"ExpiredOverlay","description":"Overlay for expired NFT display","states":["expired","renewable","permanently-expired"],"props":["expiredAt","canRenew","onRenew","onHide"]}],"antiPatterns":[{"pattern":"Hiding validity period from users","why":"Users surprised when access suddenly revoked","instead":"Always show \"Valid until [date]\" prominently","severity":"critical"},{"pattern":"No warning before expiration","why":"Users may miss a relevant access deadline or supported renewal window.","instead":"Choose reminders appropriate to the actual validity period and supported renewal policy; let users control notifications.","severity":"high"},{"pattern":"Treating expired NFTs same as active","why":"Confusing when NFT appears valid but doesn't work","instead":"Visually distinguish expired tokens (gray out, badge)","severity":"critical"},{"pattern":"Not showing future-starting passes clearly","why":"User thinks NFT is broken when it's just not active yet","instead":"Show \"Activates in X days\" with clear start date","severity":"high"},{"pattern":"Complex renewal process","why":"Users give up on renewing, churn increases","instead":"Offer renewal only when the target contract supports an authorized update or reissue path","severity":"medium"},{"pattern":"Burning expired NFTs automatically","why":"Users lose collectible/proof they had membership","instead":"Keep expired NFT visible, just mark as expired","severity":"medium"}],"keyTakeaways":["ERC-5007 = NFT with standardized start and end timestamp fields","Useful for subscriptions, season passes, and memberships when a consuming implementation applies the fields","Always show validity period prominently","Warn before expiration when the consuming app enforces the timestamps","Keep expired NFTs visible, just marked as expired"],"technicalNotes":"ERC-5007 extends ERC-721 with startTime(tokenId) and endTime(tokenId), each returning a uint64 UNIX timestamp. It does not define a renewal or update function and does not impose a universal utility or transfer gate; consuming contracts choose whether and how to check the fields, including boundary inclusivity. The optional composable extension adds split/merge operations. Common uses include subscription or rental windows when the target implementation applies the timestamps.","lastUpdated":"2026-09-18","specConstraints":[{"id":"split-input-exists","constraint":"A split operation requires an existing input token ID.","appliesTo":"application","normativity":"normative","specQuote":"* - `tokenId` must exist.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5007#specification","designImplication":"Require the user to select an existing token before offering a split action and show an unavailable state for a missing token."},{"id":"merge-input-exists","constraint":"A merge operation requires existing input token IDs.","appliesTo":"application","normativity":"normative","specQuote":"* - `firstTokenId` must exist.\n* - `secondTokenId` must exist.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5007#specification","designImplication":"Show both source tokens as part of the merge review and block the action when either token no longer exists."},{"id":"split-output-unused","constraint":"New token IDs created by a split must not already exist.","appliesTo":"application","normativity":"normative","specQuote":"* - `newToken1Id` must not exist.\n* - `newToken1Owner` cannot be the zero address.\n* - `newToken2Id` must not exist.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5007#specification","designImplication":"Treat the resulting token IDs as newly minted outputs and show a conflict state if an ID is already occupied."},{"id":"merge-output-unused","constraint":"The new token ID created by a merge must not already exist.","appliesTo":"application","normativity":"normative","specQuote":"* - `newTokenId` must not exist.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5007#specification","designImplication":"Confirm the destination token ID is unused before showing the merge as ready."},{"id":"erc721-fractional-compatibility","constraint":"The standard remains fully compatible with ERC-721.","appliesTo":"application","normativity":"backwards-compatibility","specQuote":"## Backwards Compatibility\n\nThis standard is fully ERC-721 compatible.","specSection":"Backwards Compatibility","specUrl":"https://ercs.ethereum.org/ERCS/erc-5007#backwards-compatibility","designImplication":"Retain ERC-721 ownership and marketplace views around split and merge-specific states."},{"id":"composable-extension-availability","constraint":"The composable extension is OPTIONAL; it allows an NFT to be minted from an existing NFT or to merge two NFTs into one NFT.","appliesTo":"application","normativity":"normative","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5007#specification","designImplication":"Feature-detect composable support before showing split, merge, or mint-from-parent actions, and keep ordinary ERC-721 ownership available when it is absent.","specQuote":"The **composable extension** is OPTIONAL for this standard. This allows your NFT to be minted from an existing NFT or to merge two NFTs into one NFT."}],"sources":[{"label":"ERC-5007 official specification","url":"https://ercs.ethereum.org/ERCS/erc-5007","type":"official-spec"}],"lastReviewed":"2026-09-18"},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-5007","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-5007","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-5007","markdown":"https://www.eipsfordesigners.com/standards/ERC-5007/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-5007/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-5007","official":"https://ercs.ethereum.org/ERCS/erc-5007","discussion":"https://ethereum-magicians.org/search?q=ERC-5007"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}