{"id":"ERC-7858","name":"Expirable NFTs and SBTs","status":"Draft","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":"NFTs and SBTs have built-in expiration (block-based or time-based) — tokens become invalid automatically. Design implications: show expiration countdown prominently, display 'Expired' badge on invalid tokens, filter views by active/expired status, indicate expiry type (blocks vs timestamp). Design decisions: whether expired tokens remain visible or get hidden, renewal flow if supported, how to communicate 'expired but still owned' status, handling epoch-based batch expiration.","hasDetailedContent":true,"content":{"id":"ERC-7858","sources":[{"label":"Official specification","url":"https://eips.ethereum.org/EIPS/erc-7858","type":"official-spec"}],"lastReviewed":"2026-05-25","lastUpdated":"2026-05-25","summary":"NFTs and SBTs have built-in expiration (block-based or time-based) — tokens become invalid automatically.","designerTakeaways":["You can show Expires in 14 days prominently on every expiring token card.","Your filters can split Active and Expired without hiding expired items by surprise.","You can block utility actions on expired tokens with Renew to continue CTA if supported."],"applicability":{"whenToUse":["Passes, licenses, subscriptions, or seasonal badges expire.","Validity is enforced on-chain by time or block.","Renewal or re-mint extends expiry."],"whenToAvoid":["Permanent collectibles with no expiry concept.","Draft spec not deployed on target chain.","Expiry handled off-chain only."]},"prototypeFirst":[{"screen":"Expiring pass detail","why":"Holder checks validity before showing up at event.","covers":["Active countdown","Expires today","Expired"],"include":["Large expiry date","Countdown","Expired overlay"]},{"screen":"Active vs expired filter","why":"Wallets fill with old passes over time.","covers":["Filter active","Show expired archive"],"include":["Tab toggle","Expired gray treatment","Count badges"]},{"screen":"Renewal flow","why":"Extend expiry without losing identity of token if supported.","covers":["Renew available","Renew completed"],"include":["Renew CTA","New expiry preview","Payment step"]},{"screen":"Batch epoch expiry","why":"Many tokens expire together — communicate scale.","covers":["Epoch warning","Post-epoch expired set"],"include":["Batch expiry notice","Affected count","Bulk renew if offered"]}],"mentalModel":[{"label":"Expiry timestamp","description":"On-chain moment after which token is invalid for utility."},{"label":"Active vs expired","description":"Binary validity state — UI must reflect on every load."},{"label":"Still owned but expired","description":"User keeps NFT in wallet; it just no longer works."},{"label":"Renewal","description":"Optional path to extend expiry without new mint."},{"label":"Epoch batch","description":"Group expiry — many tokens die together at season end."}],"statesToDesign":[{"state":"Active — far from expiry","trigger":"Valid with long runway.","userNeed":"Glance validity.","designResponse":"Subtle Expires [date] on card."},{"state":"Expiring soon","trigger":"Within warning window.","userNeed":"Renew or use before deadline.","designResponse":"Amber countdown and notification."},{"state":"Expired — still in wallet","trigger":"Past expiry.","userNeed":"Know unusable; optional archive.","designResponse":"Expired badge; utility actions disabled."},{"state":"Renewal in progress","trigger":"User extending expiry.","userNeed":"Track new date.","designResponse":"Pending renewal with new expiry preview."},{"state":"Epoch batch expired","trigger":"Season ended.","userNeed":"Understand all related tokens expired.","designResponse":"Banner on collection: Season ended; passes expired."}],"designDecisions":[{"question":"Hide expired tokens?","recommendation":"Default Active filter; Expired tab for archive.","rationale":"Hiding surprises users who expect history."},{"question":"How alarming is expiry UI?","recommendation":"Amber at 30 days; red only day-of and after.","rationale":"Constant red creates alert fatigue."},{"question":"Show block-based expiry to users?","recommendation":"Convert to approximate time with Block-based note in advanced.","rationale":"Block numbers are meaningless to most users."}],"problemsSolved":[{"problem":"Expired passes still look valid","oldWay":"Same artwork with no date","newWay":"Expired badge and disabled utility","impact":"high"},{"problem":"Missed renewals","oldWay":"No countdown on subscription NFTs","newWay":"Prominent expiry and notifications","impact":"high"},{"problem":"Wallet clutter from dead tokens","oldWay":"All tokens mixed together","newWay":"Active/Expired filters","impact":"medium"}],"uxPatterns":[{"name":"Expiry Countdown Chip","description":"Prominent deadline on expiring tokens.","mockup":"concept/nft-gallery","components":["ExpiryChip","CountdownTimer","ExpiredOverlay"],"userFlow":["Load token","Read expiry","Show countdown","Switch to Expired after date"]},{"name":"Active Expired Filter","description":"Split wallet views by validity.","mockup":"concept/verify-safety","components":["FilterTabs","ExpiredArchive","RenewCTA"],"userFlow":["Open wallet","Default Active","Switch to Expired","Optional renew"]}],"seenInTheWild":[{"app":"POAP","url":"https://poap.xyz/","note":"Event badges with implicit time bounds inform expiry UX."},{"app":"Unlock Protocol","url":"https://unlock-protocol.com/","note":"Time-bound membership NFTs with renewal patterns."},{"app":"Guild","url":"https://guild.xyz/","note":"Role passes with expiration inform countdown design."}],"antiPatterns":[{"pattern":"No expiry visible on pass NFT","why":"Users denied entry at door","instead":"Expiry date on thumbnail and detail header","severity":"critical"},{"pattern":"Deleting expired tokens from wallet UI","why":"Users lose proof they held pass","instead":"Expired archive tab","severity":"medium"},{"pattern":"Showing block number as expiry","why":"Meaningless to users","instead":"Human datetime with advanced block note","severity":"high"}],"vocabulary":[{"use":"Valid until [date]","avoid":"Expiry block 18293482","why":"Human deadlines."},{"use":"Expired","avoid":"Validity epoch ended","why":"Plain status."},{"use":"Renew pass","avoid":"Extend expiration timestamp","why":"Subscription-familiar action."}],"onMonad":[{"aspect":"Expiry precision","ethereum":"Block time variance affects countdown","monad":"Consistent block times improve countdown accuracy","designImplication":"Show tighter countdown windows on Monad."},{"aspect":"Renewal txs","ethereum":"Users skip renew due to gas","monad":"Low fees encourage proactive renewal","designImplication":"One-tap renew without gas warning modal."}],"technicalNotes":"ERC-7858 is draft; re-read expiry on every view — do not cache past validity.","relatedStandards":[{"id":"ERC-5192","relationship":"Soulbound tokens often expire"},{"id":"ERC-4907","relationship":"Rental expiry separate from token expiry"}]},"sources":[{"label":"Official specification","url":"https://eips.ethereum.org/EIPS/erc-7858","type":"official-spec"},{"label":"Discussion","url":"https://ethereum-magicians.org/search?q=ERC-7858","type":"discussion"},{"label":"Official specification","url":"https://eips.ethereum.org/EIPS/erc-7858","type":"official-spec"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-7858","markdown":"https://www.eipsfordesigners.com/standards/ERC-7858/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-7858/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-7858","official":"https://eips.ethereum.org/EIPS/erc-7858","discussion":"https://ethereum-magicians.org/search?q=ERC-7858"},"freshness":{"lastReviewed":"2026-05-25","lastUpdated":"2026-05-25"}}