{"id":"ERC-7432","name":"Non-Fungible Token Roles","status":"Final","chain":"both","category":{"id":"nft","name":"NFT Capabilities","description":"What NFTs can do beyond basic ownership"},"journeyStages":[{"id":"approving","name":"Approving & Permissioning","description":"Granting permissions for actions"},{"id":"management","name":"Asset Management","description":"Managing assets over time"}],"uxImpact":"ERC-7432 defines NFT role records with recipients, expiration, revocation policy, custom data, approval, and lock/unlock behavior. It does not define a role marketplace, price, purchase flow, or escrow; those are optional application layers over a verified role policy.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-7432","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-7432","sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-7432","type":"official-spec"}],"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","summary":"ERC-7432 defines NFT role records with recipients, expiration, revocation policy, custom data, approval, and lock/unlock behavior. It does not define a role marketplace, price, purchase flow, or escrow; those are optional application layers over a verified role policy.","designerTakeaways":["You can display role chips on every NFT card — Manager until Mar 12, not raw role id 3.","Your assign flow can pick role type, recipient, and expiry in one guided sheet.","You can disable owner-only actions for role holders with clear This requires owner copy."],"applicability":{"whenToUse":["The target implementation exposes ERC-7432 role assignment and the app can read recipient, expiry, revocation, approval, and custom data.","Multiple parties need distinct access to an NFT or related asset without transferring ownership.","The product can explain which actions each role actually authorizes."],"whenToAvoid":["The target contract does not expose the role interface or its authorization rules are unknown.","A simple owner/user model is enough; ERC-4907 may be a closer fit.","The product needs a marketplace, price, purchase, or escrow flow that has not been separately implemented."]},"prototypeFirst":[{"screen":"NFT detail role roster","why":"Users need to see which addresses hold which roles and when they expire.","covers":["Multiple roles","Expired role","Empty"],"include":["Role chips","Holder address","Expiry per role","Assign role CTA"]},{"screen":"Assign role sheet","why":"Owners or authorized operators need to review recipient, expiry, and permission scope.","covers":["Pick role","Set expiry","Confirm"],"include":["Role picker","Recipient field","Expiry date","Permission summary"]},{"screen":"Role holder view","why":"Delegates need to know what the target policy lets them do.","covers":["Active role","Expired","Revoked"],"include":["Role banner","Allowed actions from target policy","Expiry countdown"]},{"screen":"Optional application offer","why":"A marketplace can be layered on top, but ERC-7432 itself has no listing or purchase semantics.","covers":["Offer available","No offer","Expired offer"],"include":["Application terms","Role policy","Price and settlement source"]}],"mentalModel":[{"label":"Owner","description":"Can assign roles when owner or approved; revocation depends on recipient, revocable, and approval state."},{"label":"Role assignment","description":"Permission bundle granted to another address for a period."},{"label":"Role expiry","description":"Role access ends at expiration; a revocation transaction may still be required for cleanup."},{"label":"Custom role data","description":"Extra fields per role — show human summary, not raw bytes."},{"label":"Action gating","description":"Buttons enable based on caller role, not just ownership."}],"statesToDesign":[{"state":"Owner or approved operator","trigger":"Viewer is token owner or approved operator and the role's approval rules permit management.","userNeed":"Know which role actions are available.","designResponse":"Show role management actions only after checking approval and each role's revocable flag."},{"state":"Active role holder","trigger":"Viewer holds non-owner role.","userNeed":"Know permitted actions and expiry.","designResponse":"Role banner with allowed actions; owner actions hidden."},{"state":"Role expiring soon","trigger":"Expiry within warning window.","userNeed":"Renew or finish tasks.","designResponse":"Amber countdown on role chip and notification."},{"state":"Expired role","trigger":"Past the role's expirationDate.","userNeed":"Understand permissions ended.","designResponse":"Expired badge; disabled former actions with explanation."},{"state":"Role revoked","trigger":"An authorized owner, operator, or recipient revoked the role early.","userNeed":"Not assume access remains.","designResponse":"Access ended notice; remove role from active roster."}],"designDecisions":[{"question":"How many roles to show on thumbnail?","recommendation":"Max two chips plus +N more on card.","rationale":"Dense role lists clutter grids."},{"question":"Friendly names vs role ids?","recommendation":"Map ids to names from contract metadata or app config.","rationale":"Role id 4 means nothing to users."},{"question":"Notify on expiry?","recommendation":"Push or email before expiry for high-value roles.","rationale":"Silent expiry causes failed critical actions."}],"problemsSolved":[{"problem":"Only owner can act on NFT","oldWay":"Transfer NFT to delegate temporarily","newWay":"Grant Manager role while retaining ownership","impact":"high"},{"problem":"Unclear who can use an asset","oldWay":"Try action and revert","newWay":"Role roster visible before interaction","impact":"high"},{"problem":"Forgotten delegations","oldWay":"Roles linger without visibility","newWay":"Expiry countdowns and revoke controls when the role's revocation rules authorize them","impact":"medium"}],"uxPatterns":[{"name":"Role Roster Panel","description":"List roles, holders, expiry, and revocation policy alongside the selected asset.","components":["RoleChip","HolderRow","ExpiryTimer","AssignButton"],"userFlow":["Open the relevant asset","Read roles and target contract state","Assign or revoke only when authorized","Roster updates after settlement"]},{"name":"Role-Gated Actions","description":"Enable controls from the target role and approval policy, not from the role label alone.","components":["ActionButton","RoleGate","OwnerOnlyTooltip"],"userFlow":["User views an action","UI checks role, expiry, and target policy","Permitted actions are enabled","Blocked actions explain the missing authorization"]}],"antiPatterns":[{"pattern":"Showing only owner with no role list","why":"Delegates discover limits at revert","instead":"Role roster on every detail page","severity":"high"},{"pattern":"Displaying raw role id integers","why":"Meaningless to users","instead":"Friendly role names from metadata","severity":"medium"},{"pattern":"No expiry warning","why":"Silent permission loss mid-task","instead":"Countdown and notification before expiry","severity":"high"}],"vocabulary":[{"use":"Manager until [date]","avoid":"Role 0x3 assigned","why":"Human role labels with expiry."},{"use":"Assign access","avoid":"Grant role bitmap","why":"Permission language over encoding."},{"use":"Requires owner","avoid":"onlyOwner modifier revert","why":"Plain gating explanation."}],"specConstraints":[{"id":"role-metadata","constraint":"Role-aware DApps must support ERC-721 metadata when using the optional roles metadata extension.","appliesTo":"application","normativity":"normative","specQuote":"The Roles Metadata extension extends the traditional JSON-based metadata schema of NFTs. Therefore, DApps supporting\nthis feature MUST also implement the metadata extension of [ERC-721](./eip-721.md). This extension is **optional** and allows\ndevelopers to provide additional information for roles.","specSection":"Specification > Metadata Extension","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#metadata-extension","designImplication":"Show role metadata alongside the NFT identity and keep optional role metadata distinct from the authoritative role record."},{"id":"role-grant-authority-expiry","constraint":"grantRole must reject expired roles and callers not approved to grant on behalf of the NFT owner.","appliesTo":"application","normativity":"normative","specQuote":"* The `grantRole` function MUST revert if the `expirationDate` is in the past or if the `msg.sender` is not approved to\n  grant roles on behalf of the NFT owner. It MAY be implemented as `public` or `external`.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Role assignment forms should validate expiry and authority before signing and explain whether the connected account can grant the role."},{"id":"role-lock-state","constraint":"Granting a frozen or escrowed role must emit a lock signal in addition to RoleGranted.","appliesTo":"application","normativity":"normative","specQuote":"* In addition to emitting the `RoleGranted` event, the `grantRole` function MUST emit a `TokenLocked` event if the token\n  is frozen or transferred to an escrow account.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Show a role as locked/escrowed rather than available when the grant produces the token-locked state."},{"id":"role-revoke-authority","constraint":"revokeRole must reject callers without owner or recipient authority.","appliesTo":"application","normativity":"normative","specQuote":"* The `revokeRole` function MUST revert if the `msg.sender` is not approved to revoke roles on behalf of the original\n  NFT owner or the `recipient`. It MAY be implemented as `public` or `external`.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Disable revoke controls for unauthorized viewers and state whether the owner or role recipient is the available authority."},{"id":"role-unlock-guard","constraint":"unlockToken must reject unauthorized callers and remain locked while a non-revocable, unexpired role exists.","appliesTo":"application","normativity":"normative","specQuote":"* The `unlockToken` function MUST revert if the `msg.sender` is not approved, or if there is at least one non-revocable\n  role not expired. It MAY be implemented as `public` or `external`.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Explain the blocking role and its expiry/revocability before showing an unlock action."},{"id":"role-owner-record","constraint":"The role record exposes the original NFT owner.","appliesTo":"application","normativity":"normative","specQuote":"* The `ownerOf` function MAY be implemented as `pure` or `view`, and MUST return the address of the original owner of\n  the NFT.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Display original owner separately from current recipient and current wallet authority."},{"id":"role-recipient-record","constraint":"The role record exposes the account that received the role.","appliesTo":"application","normativity":"normative","specQuote":"* The `recipientOf` function MAY be implemented as `pure` or `view`, and MUST return the address of the account that\n  received the role.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Show who currently holds the role and avoid conflating the role recipient with the NFT owner."},{"id":"role-data-record","constraint":"The role record exposes the encoded data supplied at grant time.","appliesTo":"application","normativity":"normative","specQuote":"* The `roleData` function MAY be implemented as `pure` or `view`, and MUST return the encoded data passed to the\n  `grantRole` function.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Expose human-readable role metadata when available and provide a safe fallback for opaque custom data."},{"id":"role-expiration-record","constraint":"The role record exposes its expiration date.","appliesTo":"application","normativity":"normative","specQuote":"* The `roleExpirationDate` function MAY be implemented as `pure` or `view`, and MUST return the expiration date of a\n  given role.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Use explicit expiry states, countdowns, and renewal/reassignment affordances where the integration supports them."},{"id":"role-revocability-record","constraint":"The role record exposes whether the role is revocable.","appliesTo":"application","normativity":"normative","specQuote":"* The `isRoleRevocable` function MAY be implemented as `pure` or `view`, and MUST return whether the role is revocable.","specSection":"Specification > Caveats","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#caveats","designImplication":"Label non-revocable roles clearly before assignment and use that state in unlock/revoke explanations."},{"id":"role-approval","constraint":"Approved accounts can manage roles on behalf of the NFT owner through role-approval functions.","appliesTo":"application","normativity":"rationale","specQuote":"Similar to [ERC-721](./eip-721.md), this standard enable other accounts to manage roles on behalf of the NFT owner. This\nfunctionality was introduced to allow third-parties to interact with ERC-7432 without requiring NFT ownership. Compliant\ncontracts MUST implement the functions `setRoleApprovalForAll` and `isRoleApprovedForAll` to deliver this feature.","specSection":"Rationale > Role Approval","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#role-approval","designImplication":"Show role-manager permissions separately from NFT ownership and provide a clear approval/revocation path."},{"id":"role-source-identity","constraint":"tokenAddress and tokenId identify the authoritative NFT role source, including in a standalone role contract.","appliesTo":"application","normativity":"backwards-compatibility","specQuote":"## Backwards Compatibility\n\nOn all functions and events, the standard requires both the `tokenAddress` and `tokenId` to be provided. This \nrequirement enables dApps to use a standalone [ERC-7432](./eip-7432.md) contract as the authoritative source for the\nroles of immutable NFTs.","specSection":"Backwards Compatibility","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#backwards-compatibility","designImplication":"Keep collection address and token ID visible in role detail so users can verify which NFT governs the role."},{"id":"role-security","constraint":"Role integrations require access controls, reentrancy awareness, escrow boundaries, and expiry checks.","appliesTo":"application","normativity":"security-considerations","specQuote":"## Security Considerations\n\nDevelopers integrating the Non-Fungible Token Roles interface should consider the following on their implementations:\n\n* Ensure proper access controls are in place to prevent unauthorized role assignments or revocations.\n* Take into account potential attack vectors such as reentrancy and ensure appropriate safeguards are in place.\n* Approved accounts should be able to manage roles on behalf of another user. However, ensure that the NFT can\n  only be transferred to an escrow contract, and back to its original owner (not to the approved account).\n* Always check the expiration date before allowing users to access the utility of an NFT.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#security-considerations","designImplication":"Separate owner, approved manager, recipient, locked, and expired states; never grant utility access solely from a role label without checking expiry and authority."},{"id":"role-metadata-guidance","constraint":"Role metadata properties are suggested, and it is RECOMMENDED to use Solidity ABI type and components for role inputs.","appliesTo":"application","normativity":"normative","specQuote":"The `roles` array properties are SUGGESTED, and developers should add any other relevant information as necessary (e.g.,\nan image for the role). It's also important to highlight the importance of the `inputs` property. This field describes\nthe parameters that should be encoded and passed to the `grantRole` function. It's RECOMMENDED to use the properties\n`type` and `components` defined on the Solidity ABI Specification, where `type` is the canonical type of the parameter,\nand `components` is used for complex tuple types.","specSection":"Specification > Metadata Extension","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#metadata-extension","designImplication":"Use the recommended ABI metadata when it exists to render role parameters clearly, but keep the UI resilient to additional or custom role metadata."},{"id":"recipient-revocation","constraint":"It is RECOMMENDED to enable the role recipient to revoke roles so undesirable assignments can be eliminated.","appliesTo":"application","normativity":"rationale","specQuote":"Regardless of the value of `revocable`, it's recommended always to enable the `recipient` to revoke roles, allowing them\nto eliminate undesirable assignments.","specSection":"Rationale > Revocable Roles","specUrl":"https://ercs.ethereum.org/ERCS/erc-7432#revocable-roles","designImplication":"Give recipients a visible revoke or relinquish path when supported, and explain when the token's implementation does not expose it; this remains a recommendation, not a mandatory contract behavior."}],"technicalNotes":"ERC-7432 is a role-management interface, not an ERC-721 extension; it may be implemented externally or alongside an NFT. Show each role's recipient, expirationDate, revocable flag, custom data, and approval state. If revocable is false, only the recipient can revoke; if true, the recipient and original owner can revoke, and unlockToken must remain blocked while an unexpired non-revocable role exists.","relatedStandards":[{"id":"ERC-4907","relationship":"Simpler user/owner dual role model"},{"id":"ERC-721","relationship":"Role manager that may be colocated with or managed alongside an NFT implementation"}]},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-7432","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-7432","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-7432","markdown":"https://www.eipsfordesigners.com/standards/ERC-7432/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-7432/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-7432","official":"https://ercs.ethereum.org/ERCS/erc-7432","discussion":"https://ethereum-magicians.org/search?q=ERC-7432"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}