ERC-6366 Permission token standard (Permission Token)

Review · Signatures & auth · created 2022-01-19

A standard that stores the permissions held by an address as bits within a single uint256 number, and allows them to be transferred or delegated like a token. Permission checks are handled quickly using bitwise operations.

Why it is needed

Smart contracts commonly have special roles such as Owner, Operator, Manager, and Validator, and addresses holding these permissions manage the contract. However, when such permissions are managed separately in each contract, they cannot be viewed in one place, making them hard to audit and hard to maintain. In addition, the existing Access Control List (ACL) approach checks permissions by comparing strings or keccak256 hashes, which is costly and inflexible. This standard proposes a much more efficient and flexible alternative by representing permissions as bits within a single uint256 and checking them with bitwise operators and bitmasks. Since permissions and roles are expressed through the permission token balance an account holds within the given ecosystem, interoperability across multiple ecosystems also becomes simpler.

What to implement

In depth

Representing permissions as uint256 bits

A single address's entire permission set is stored in one uint256 value. As described in ERC-6617, each permission corresponds to one bit of the uint256. Whether a permission is included is determined using bitwise operators and bitmasks, and the original text explains that this approach is far more efficient and flexible than string or keccak256 comparison. Defining each permission as a power of two is RECOMMENDED, since that allows ERC-6617 to check subset relationships between permission sets. Compliant contracts MUST implement IEIP6366Core, and this standard requires ERC-6617 as a prerequisite.

Transfer behavior rules

transfer(_to, _permission) transfers the permission subset _permission to _to. It SHOULD revert if the caller's account does not hold the subset of permissions being transferred. It SHOULD also revert if any of the permissions being transferred already exist on the target address _to. The Transfer event MUST fire whenever a permission is transferred, including when transferring a zero permission.

Delegation via approve and delegated

approve(_delegatee, _permission) allows a delegatee to act on behalf of the permission holder within the scope of _permission. Calling the same function again overwrites the currently approved value with the new _permission. It SHOULD revert if the _permission being granted is not a subset of the holder's full permission set. Every successful call MUST fire an Approval event. delegated(_owner, _delegatee) returns the subset of permissions the holder has granted to the delegatee.

Three query functions

permissionOf(_owner) returns the permission set of the given address. permissionRequire(_permission, _required) is a pure set-comparison function that returns true if _required is a subset of _permission. hasPermission(_owner, _actor, _required) returns true if _required is a subset of _actor's own permissions, or a subset of the permissions delegated by _owner. In other words, it checks the actor's own permissions and delegated permissions in a single call.

Metadata and error interfaces

Compliant contracts are RECOMMENDED to implement the optional extension IEIP6617Meta. Descriptions SHOULD be defined for base permissions and major combinations, but descriptions SHOULD NOT be defined for every possible sub-combination. Compatible tokens MAY also implement IEIP6366Error, which defines three errors: AccessDenied when a required permission is missing, DuplicatedPermission when permission sets conflict, and OutOfRange when data is out of range.

A proposal still under review

This proposal's status is Review, meaning its contents may still change. The original text's Rationale section only states "Needs discussion," and the Security Considerations section only states "Need more discussion," so the design rationale and security considerations have not yet been filled in. An ERC-6366 Core implementation file is provided as the reference implementation.

Original ERC · ← ERCs