{"id":"ERC-5496","name":"Multi-privilege Management NFT","status":"Last Call","chain":"both","category":{"id":"security","name":"Security & Trust","description":"Helping users verify, control, and protect their assets"},"journeyStages":[{"id":"approving","name":"Approving & Permissioning","description":"Granting permissions for actions"}],"uxImpact":"ERC-5496 extends ERC-721 with multiple privileges that can be assigned to users and checked independently of NFT ownership. A privilege has a provider-defined expiry through privilegeExpires, and an optional cloneable extension can copy a privilege; implementations decide assignment authority and the practical access policy.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-5496","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-5496","summary":"ERC-5496 extends ERC-721 with multiple privileges that can be assigned to users and checked independently of NFT ownership. A privilege has a provider-defined expiry through privilegeExpires, and an optional cloneable extension can copy a privilege; implementations decide assignment authority and the practical access policy.","applicability":{"whenToUse":["An NFT needs separate privilege assignments for named users with queryable expiry.","The product can check hasPrivilege(tokenId, privilegeId, user) for the actual user.","Clone controls are shown only when the optional IERC721Cloneable interface is supported."],"whenToAvoid":["The NFT does not implement the privilege interface or the target user/privilege lookup.","The product needs expiry or cloning guarantees the deployed implementation does not provide.","The UI cannot distinguish token owner from privilege holder."]},"designerTakeaways":["You can show one NFT's separate privilege slots and their current holders.","You can grant a privilege to a user without transferring the NFT when the implementation authorizes it.","You can call hasPrivilege(tokenId, privilegeId, user) and show privilegeExpires for the selected user."],"problemsSolved":[{"problem":"NFTs represent only single permissions","oldWay":"Need separate NFTs for VIP access, parking, and merch discount","newWay":"One NFT can expose multiple privilege slots with separate users and expiry timestamps","impact":"critical"},{"problem":"Can't grant temporary access without full transfer","oldWay":"Lend entire NFT (and all privileges) or nothing","newWay":"The access check can ask hasPrivilege(tokenId, privilegeId, user) for a specific user","impact":"high"},{"problem":"No standard way to check multiple perks","oldWay":"Custom logic per project to track entitlements","newWay":"A product can show privilege holder and NFT owner as separate roles","impact":"high"},{"problem":"Privileges can't expire independently","oldWay":"Whole NFT valid or invalid, no per-perk expiry","newWay":"The product can query privilegeExpires and display the deployed implementation's expiry rules","impact":"medium"},{"problem":"Hard to revoke specific access without burning NFT","oldWay":"Must issue new NFT with reduced privileges","newWay":"When the optional cloneable extension is supported, a privilege can be copied through clonePrivilege; reassignment or revocation remains implementation-specific","impact":"medium"}],"uxPatterns":[{"name":"Multi-Privilege NFT Card","description":"Display all privileges on a single NFT","userFlow":["User opens a privilege-bearing NFT","Discover supported privilege IDs and assignments through the documented implementation or indexer; the base interface has no privilegeIds enumeration getter","App checks hasPrivilege(tokenId, privilegeId, user) for the connected user","Shows privilege holder, NFT owner, and privilegeExpires separately"]},{"name":"Privilege Delegation","description":"Show the privilege holder, expiry timestamp, and action scope for the selected user.","userFlow":["User selects NFT to share from","Picks specific privilege to delegate","Enters recipient address","Show the implementation's supported expiry and assignment policy before signing","Confirms transaction","Recipient gains privilege access"]},{"name":"Privilege Verification Gate","description":"Offer privilege sharing only when the deployed contract supports setPrivilege or the optional cloneable extension.","userFlow":["Gate displays required privilege","User scans QR or connects wallet","System checks hasPrivilege()","Verifies not expired","Shows if direct ownership or delegated","Grants or denies access"]},{"name":"Privilege Management Dashboard","description":"Show assignment and optional clone controls; expose revocation only when the deployed implementation supports it.","userFlow":["User opens privilege manager","Sees outgoing and received assignments","App shows any implementation-supported reassignment or revoke action","Clone controls appear only when clonePrivilege is supported","App refreshes hasPrivilege and privilegeExpires"]}],"uiComponents":[{"name":"PrivilegeBadge","description":"Visual indicator for a single privilege status","states":["active","expiring-soon","expired","assigned","unknown"],"props":["privilegeId","name","expiresAt","isDelegated"]},{"name":"PrivilegeTimeline","description":"Visual timeline of privilege validity","states":["before","active","ended"],"props":["startDate","endDate","privilegeName"]},{"name":"DelegationCard","description":"Shows assignment details and a revoke/reassignment action only when the implementation exposes one.","states":["active","expiring","revoked"],"props":["privilege","delegatee","expiresAt","onRevoke"]},{"name":"PrivilegeVerifier","description":"Real-time privilege checking component","states":["checking","verified","denied","expired"],"props":["tokenId","privilegeId","address"]}],"antiPatterns":[{"pattern":"Not showing which privileges are delegated vs owned","why":"Users confused about what they can actually use vs lend","instead":"Call hasPrivilege(tokenId, privilegeId, user) for the actual user and display privilegeExpires separately.","severity":"critical"},{"pattern":"Allowing privilege use after expiry without clear error","why":"Frustrating when access fails at the gate","instead":"Explain expiry as a timestamp read from the deployed contract; do not assume one universal duration or automatic renewal.","severity":"high"},{"pattern":"No revocation UI for delegated privileges","why":"Users can't retract access they granted","instead":"Show the implementation-supported reassignment or revoke action; offer clonePrivilege only when IERC721Cloneable is advertised.","severity":"high"},{"pattern":"Bundling all privileges into one indistinguishable token","why":"Users can't see or manage individual perks","instead":"Itemized privilege list with individual management","severity":"medium"},{"pattern":"Inventing remaining-use counters for a privilege","why":"The base interface defines privilege checks and expiry, not consumable-use counts.","instead":"Show remaining uses only when a documented extension or application policy exposes a reliable counter.","severity":"medium"}],"keyTakeaways":["ERC-5496 attaches multiple user privileges to an NFT.","hasPrivilege requires tokenId, privilegeId, and user.","Read privilegeExpires and the deployed assignment rules; expiry is not a universal product promise.","Treat cloning as an optional extension and capability-gate its UI.","Keep NFT ownership and privilege holding visibly separate."],"specConstraints":[{"id":"erc-5496-interface-support","constraint":"A compliant contract implements IERC5496; the shareable multi-privilege extension remains optional for ERC-721 contracts.","appliesTo":"application","normativity":"normative","specQuote":"Every contract complying with this standard MUST implement the `IERC5496` interface. The **shareable multi-privilege extension** is OPTIONAL for EIP-721 contracts.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#specification","designImplication":"Detect the base interface before showing privilege data, and capability-gate sharing or cloning controls instead of assuming every ERC-721 supports them."},{"id":"erc-5496-privilege-id-range","constraint":"Implementations should define a maximum privilege number and must reject privilege IDs above that maximum.","appliesTo":"application","normativity":"normative","specQuote":"Every contract implementing this standard SHOULD set a maximum privilege number before setting any privilege, the `privilegeId` MUST NOT be greater than the maximum privilege number.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#specification","designImplication":"Use the deployed contract's supported privilege range when rendering selectors or validation; do not let a client invent privilege IDs outside that range."},{"id":"erc-5496-assignment-event","constraint":"PrivilegeAssigned is emitted whenever setPrivilege is called.","appliesTo":"application","normativity":"normative","specQuote":"The `PrivilegeAssigned` event MUST be emitted when `setPrivilege` is called.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#specification","designImplication":"Refresh the privilege holder and expiry from the assignment event, and show the token, privilege, recipient, and expiry as separate fields."},{"id":"erc-5496-total-change-event","constraint":"PrivilegeTotalChanged is emitted whenever the collection's total privilege changes.","appliesTo":"application","normativity":"normative","specQuote":"The `PrivilegeTotalChanged` event MUST be emitted when the `total privilege` of the collection is changed.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#specification","designImplication":"Treat collection privilege-count changes as observable state updates and avoid presenting a stale privilege selector after the collection changes."},{"id":"erc-5496-interface-detection","constraint":"supportsInterface must return true for the IERC5496 interface identifier 0x076e1bbb.","appliesTo":"application","normativity":"normative","specQuote":"The `supportsInterface` method MUST return `true` when called with `0x076e1bbb`.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#specification","designImplication":"Use the interface check as the minimum capability gate before showing ERC-5496 privilege actions."},{"id":"erc-5496-clone-event","constraint":"PrivilegeCloned is emitted whenever clonePrivilege is called by an implementation supporting the optional cloneable extension.","appliesTo":"application","normativity":"normative","specQuote":"The `PrivilegeCloned` event MUST be emitted when `clonePrivilege` is called.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#specification","designImplication":"Show cloning as an optional capability and refresh the affected privilege from the clone event; do not imply that the base interface can clone privileges."},{"id":"erc-5496-privilege-authority","constraint":"Implementations must carefully consider who is permitted to set or clone privileges.","appliesTo":"wallet","normativity":"security-considerations","specQuote":"Implementations must thoroughly consider who has the permission to set or clone privileges.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#security-considerations","designImplication":"Show the authority and scope behind assignment or cloning before signing; a privilege UI must not imply that ownership alone proves the deployed contract's authorization policy."},{"id":"erc-5496-signature-validation","constraint":"Compliant contracts are RECOMMENDED to use EIP-1271 for signature validation.","appliesTo":"account-implementation","normativity":"normative","specQuote":"For Compliant contract, it is RECOMMENDED to use [EIP-1271](./eip-1271.md) to validate the signatures.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#specification","designImplication":"When privilege assignment or cloning involves contract accounts, support EIP-1271 as a recommended validation path rather than assuming EOA-only signatures."},{"id":"erc-5496-nft-transfer-privilege-separation","constraint":"Transferring NFT ownership does not move existing privileges, and an unwrap attempt MAY fail while privileges remain active.","appliesTo":"application","normativity":"rationale","specQuote":"If the owner of the NFT transfers ownership to another user, there is no impact on \"privileges\". But errors may occur if the owner tries to withdraw the original [EIP-721](./eip-721.md) token from the wrapped NFT through `unwrap()` if any available privileges are still ongoing. We protect the rights of holders of the privileges to check the last expiration date of the privilege.","specSection":"Rationale — Proposal: NFT Transfer","specUrl":"https://ercs.ethereum.org/ERCS/erc-5496#proposal-nft-transfer","designImplication":"Keep NFT ownership and privilege holding separate, and show the privilege expiration gate before offering an unwrap action."}],"technicalNotes":"ERC-5496 defines setPrivilege(tokenId, privilegeId, user, expires), privilegeExpires(tokenId, privilegeId), and hasPrivilege(tokenId, privilegeId, user). The specification recommends a maximum privilege number and says expires should be less than 30 days in the base interface guidance. IERC721Cloneable and clonePrivilege(tokenId, privilegeId, referrer) are optional. Privilege enumeration, remaining-use counters, and consumable behavior need separate implementation evidence.","lastUpdated":"2026-09-18","sources":[{"label":"ERC-5496 official specification","url":"https://ercs.ethereum.org/ERCS/erc-5496","type":"official-spec"}],"lastReviewed":"2026-09-18","partialDeployment":{"body":"ERC-5496 is Last Call. A live deployment has not been verified here. Confirm the target contract, network, and client support before offering these actions; specification status does not establish product availability."}},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-5496","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-5496","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-5496","markdown":"https://www.eipsfordesigners.com/standards/ERC-5496/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-5496/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-5496","official":"https://ercs.ethereum.org/ERCS/erc-5496","discussion":"https://ethereum-magicians.org/search?q=ERC-5496"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}