主页EIPs
EIPsERC-6617
ERC-6617

Bit Based Permission

A permission and role system based on bits
ReviewStandards Track: ERC
创建时间: 2023-02-27
Chiro (@chiro-hiro), Victor Dusart (@vdusart)
社区讨论原文链接编辑
1 分钟了解
欢迎补充好内容
去提交
相关视频
欢迎补充好内容
去提交
正文

Abstract

This EIP offers a standard for building a bit-based permission and role system. Each permission is represented by a single bit. By using an uint256, up to $256$ permissions and $2^{256}$ roles can be defined. We are able to specify the importance of each permission based on the order of the bits.

Specification

The key words "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.

Note The following specifications use syntax from Solidity 0.8.7 (or above)

Interface of reference is described as followed:

pragma solidity ^0.8.7; /** @title EIP-6617 Bit Based Permission @dev See https://eips.ethereum.org/EIPS/eip-6617 */ interface IEIP6617 { /** MUST trigger when a permission is granted. @param _grantor Grantor of the permission @param _permission Permission that is granted @param _user User who received the permission */ event PermissionGranted(address indexed _grantor, uint256 indexed _permission, address indexed _user); /** MUST trigger when a permission is revoked. @param _revoker Revoker of the permission @param _permission Permission that is revoked @param _user User who lost the permission */ event PermissionRevoked(address indexed _revoker, uint256 indexed _permission, address indexed _user); /** @notice Check if user has permission @param _user Address of the user whose permission we need to check @param _requiredPermission The required permission @return True if the _permission is a superset of the _requiredPermission else False */ function hasPermission(address _user, uint256 _requiredPermission) external view returns (bool); /** @notice Add permission to user @param _user Address of the user to whom we are going to add a permission @param _permissionToAdd The permission that will be added @return The new permission with the _permissionToAdd */ function grantPermission(address _user, uint256 _permissionToAdd) external returns (bool); /** @notice Revoke permission from user @param _user Address of the user to whom we are going to revoke a permission @param _permissionToRevoke The permission that will be revoked @return The new permission without the _permissionToRevoke */ function revokePermission(address _user, uint256 _permissionToRevoke) external returns (bool); }
  • Compliant contracts MUST implement IEIP6617
  • A permission in a compliant contract is represented as an uint256. A permission MUST take only one bit of an uint256 and therefore MUST be a power of 2. Each permission MUST be unique and the 0 MUST be used for none permission.

Metadata Interface

It is RECOMMENDED for compliant contracts to implement the optional extension IEIP6617Meta.

  • They SHOULD define a name and description for the base permissions and main combinaison.

  • They SHOULD NOT define a description for every subcombinaison of permissions possible.

/** * @dev Defined the interface of the metadata of EIP6617, MAY NOT be implemented */ interface IEIP6617Meta { /** Structure of permission description @param _permission Permission @param _name Name of the permission @param _description Description of the permission */ struct PermissionDescription { uint256 permission; string name; string description; } /** MUST trigger when the description is updated. @param _permission Permission @param _name Name of the permission @param _description Description of the permission */ event UpdatePermissionDescription(uint256 indexed _permission, string indexed _name, string indexed _description); /** Returns the description of a given `_permission`. @param _permission Permission */ function getPermissionDescription(uint256 _permission) external view returns (PermissionDescription memory description); /** Return `true` if the description was set otherwise return `false`. It MUST emit `UpdatePermissionDescription` event. @param _permission Permission @param _name Name of the permission @param _description Description of the permission */ function setPermissionDescription(uint256 _permission, string memory _name, string memory _description) external returns (bool success); }

Rationale

Currently permission and access control is performed using a single owner (ERC-173) or with bytes32 roles (ERC-5982). However, using bitwise and bitmask operations allows for greater gas-efficiency and flexibility.

Gas cost efficiency

Bitwise operations are very cheap and fast. For example, doing an AND bitwise operation on a permission bitmask is significantly cheaper than calling any number of LOAD opcodes.

Flexibility

With the 256 bits of the uint256, we can create up to 256 different permissions which leads to $2^{256}$ unique combinations (a.k.a. roles). (A role is a combination of multiple permissions). Not all roles have to be predefined.

Since permissions are defined as unsigned integers, we can use the binary OR operator to create new role based on multiple permissions.

Ordering permissions by importance

We can use the most significant bit to represent the most important permission, the comparison between permissions can then be done easily since they all are uint256s.

Associate a meaning

Compared with access control managed via ERC-5982, this EIP does not provide a direct and simple understanding of the meaning of a permission or role.

To deal with this problem, you can set up the metadata interface, which associates a name and description to each permission or role.

Reference Implementation

First implementation could be found here:

Security Considerations

No security considerations.

Copyright and related rights waived via CC0.

扩展阅读
欢迎补充好内容
去提交
相关项目
欢迎补充好内容
去提交

不想错过最新的 EIP 动态?

订阅 EIPs Fun 周刊以跟进相关更新,建⽴你与 EIP 之间的连接 ,更好地建设以太坊。

详情
支持以太坊贡献者,推动生态建设
资源
GitHub
支持社区