ERC-7432: Non-Fungible Token Roles

Role Management for NFTs. Enables accounts to share the utility of NFTs via expirable role assignments.


Metadata
Status: Last CallStandards Track: ERCCreated: 2023-07-14
Authors
Ernani São Thiago (@ernanirst), Daniel Lima (@karacurt)
Requires

Abstract


This standard introduces role management for NFTs. Each role assignment is associated with a single NFT and expires automatically at a given timestamp. Roles are defined as bytes32 and feature a custom data field of arbitrary size to allow customization.

Motivation


The NFT Roles interface aims to establish a standard for role management in NFTs. Tracking on-chain roles enables decentralized applications (dApps) to implement access control for privileged actions, e.g., minting tokens with a role (airdrop claim rights).

NFT roles can be deeply integrated with dApps to create a utility-sharing mechanism. A good example is in digital real estate. A user can create a digital property NFT and grant a keccak256("PropertyManager()") role to another user, allowing them to delegate specific utility without compromising ownership. The same user could also grant a keccak256("PropertyTenant(uint256)") role to other users, allowing the recipient to access and interact with the digital property.

There are also interesting use cases in decentralized finance (DeFi). Insurance policies could be issued as NFTs, and the beneficiaries, insured, and insurer could all be on-chain roles tracked using this standard.

Specification


The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC-2119 and RFC-8174.

Compliant contracts MUST implement the following interface:


Metadata Extension

The Roles Metadata extension extends the traditional JSON-based metadata schema of NFTs. Therefore, DApps supporting this feature MUST also implement the metadata extension of ERC-721. This extension is optional and allows developers to provide additional information for roles.

Updated Metadata Schema:


The following JSON is an example of ERC-7432 Metadata:


The roles array properties are SUGGESTED, and developers should add any other relevant information as necessary (e.g., an image for the role). It's also important to highlight the importance of the inputs property. This field describes the parameters that should be encoded and passed to the grantRole function. It's RECOMMENDED to use the properties type and components defined on the Solidity ABI Specification, where type is the canonical type of the parameter, and components is used for complex tuple types.

Caveats

  • Compliant contracts MUST implement the IERC7432 interface.
  • A role is represented by a bytes32, and it's RECOMMENDED to use the keccak256 of the role's name with its inputs: bytes32 roleId = keccak256("RoleName(input_type)").
  • The grantRole function MUST revert if the expirationDate is in the past or if the msg.sender is not approved to grant roles on behalf of the NFT owner. It MAY be implemented as public or external.
  • In addition to emitting the RoleGranted event, the grantRole function MUST emit a TokenLocked event if the token is frozen or transferred to an escrow account.
  • The revokeRole function MUST revert if the msg.sender is not approved to revoke roles on behalf of the original NFT owner or the recipient. It MAY be implemented as public or external.
  • If revocable is false, only the recipient can revoke the role. If revocable is true, both the recipient and the original NFT owner can revoke the role.
  • The unlockToken function MUST revert if the msg.sender is not approved, or if there is at least one non-revocable role not expired. It MAY be implemented as public or external.
  • The setRoleApprovalForAll function MAY be implemented as public or external.
  • The ownerOf function MAY be implemented as pure or view, and MUST return the address of the original owner of the NFT.
  • The recipientOf function MAY be implemented as pure or view, and MUST return the address of the account that received the role.
  • The roleData function MAY be implemented as pure or view, and MUST return the encoded data passed to the grantRole function.
  • The roleExpirationDate function MAY be implemented as pure or view, and MUST return the expiration date of a given role.
  • The isRoleRevocable function MAY be implemented as pure or view, and MUST return whether the role is revocable.
  • The isRoleApprovedForAll function MAY be implemented as pure or view, and SHOULD only return true if the _operator is approved to grant and revoke roles on behalf of the original NFT owner.
  • Compliant contracts SHOULD implement ERC-165.

Rationale


ERC-7432 IS NOT an extension of ERC-721. The main reason behind this decision is to enable it to be implemented externally or on the same contract as the NFT, allowing dApps to implement roles with immutable assets. This standard covers many crucial features, such as automatic expiration and custom data, but perhaps the most important one is its flexibility in implementation. ERC-7432 can be implemented in many ways, and for this reason, the neutral term "lock" is employed. This term can refer to an NFT being frozen (preventing transfers until roles expire) or deposited in an escrow contract. Developers should decide which implementation to use based on their use cases.

Automatic Expiration

Automatic expiration is implemented via the grantRole and roleExpirationDate functions. grantRole is responsible for setting the expiration date, and roleExpirationDate allow developers to check whether the role is expired. Since uint256 is not natively supported by most programming languages, dates are represented as uint64 on this standard. The maximum UNIX timestamp represented by a uint64 is about the year 584,942,417,355, which should be enough to be considered "permanent". For this reason, it's recommended using type(uint64).max to support use cases that require a role never to expire.

Revocable Roles

In certain scenarios, the original owner of the NFT may need to revoke a role before its expiration date, while in others, the recipient may require assurance that the role cannot be revoked. The revocable parameter was introduced to the grantRole function to specify whether a role can be revoked prematurely, enabling the standard to support both use cases.

Regardless of the value of revocable, it's recommended always to enable the recipient to revoke roles, allowing them to eliminate undesirable assignments.

Custom Data

DApps can customize roles using the data parameter of the grantRole function. data is implemented using the generic type bytes to enable dApps to encode any role-specific information when granting a role. The custom data is retrievable using the roleData function and is emitted with the RoleGranted event. With this approach, developers can integrate this information into their applications, both on-chain and off-chain.

Role Approval

Similar to ERC-721, this standard enable other accounts to manage roles on behalf of the NFT owner. This functionality was introduced to allow third-parties to interact with ERC-7432 without requiring NFT ownership. Compliant contracts MUST implement the functions setRoleApprovalForAll and isRoleApprovedForAll to deliver this feature.

Backwards Compatibility


On all functions and events, the standard requires both the tokenAddress and tokenId to be provided. This requirement enables dApps to use a standalone ERC-7432 contract as the authoritative source for the roles of immutable NFTs.

Reference Implementation


See ERC-7432.sol.

Security Considerations


Developers integrating the Non-Fungible Token Roles interface should consider the following on their implementations:

  • Ensure proper access controls are in place to prevent unauthorized role assignments or revocations.
  • Take into account potential attack vectors such as reentrancy and ensure appropriate safeguards are in place.
  • Approved accounts should be able to manage roles on behalf of another user. However, ensure that the NFT can only be transferred to an escrow contract, and back to its original owner (not to the approved account).
  • Always check the expiration date before allowing users to access the utility of an NFT.

Copyright


Copyright and related rights waived via CC0.