openzeppelin 的 AccessControl 权限控制


什么是 openzeppelin?

openzeppelin 是是 solidity 开发中较流行的, 用于安全智能合约开发的库。里面包含众多常用功能。如 ERC20, ERC721标准库, 角色权限控制等。
在这里主要讲 openzeppelin 的权限控制模块:
安装
npm install @openzeppelin/contracts

控制结构分析:

在 openzeppelin 的一个权限下,有两个属性 在 openzeppelin 的一个权限下,有两个属性
  • members:成员,拥有这个权限的账号。
  • adminRole: 标记父级权限, 设置后 拥有 adminRole 的角色可以控制 这个role,执行 revoke (撤销) 和 grant (授予)role的操作。还有一种情况, 拥有 DEFAULT_ADMIN_ROLE 这个权限的账户可以 grantRole 和 revokeRole 一切权限.

常用方法:

  • _setupRole 新建权限
  • grantRole 授予权限
  • revokeRole 撤销权限

示例代码

我这里定义了一个GLOBAL_ROLE方法,用来控制权限,可以根据自己的需求创建更多的权限:
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract NFT is ERC721("NFT-NAME", "SYMBOL"), AccessControl {
    bytes32 public constant GLOBAL_ROLE = keccak256("GLOBAL_ROLE");

    // 定义一个拦截器用来判断权限
    modifier auth(bytes32 iRrole) {
        require(hasRole(iRrole, msg.sender), "Permission denied");
        _;
    }

    constructor(){
        // 初始化规则
        _setupRole(GLOBAL_ROLE, msg.sender);
        // 如果需要设置一个 所有角色的默认管理员角色 ,可以加上这行
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
        // 如果不设置默认管理员,可以自己加一个管理员,记得自己定义一下
        // _setRoleAdmin(GLOBAL_ROLE, DEFAULT_ADMIN_ROLE);
    }

    // 如果继承了多个 supportsInterface 有冲突,需要重写一下
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, AccessControl) returns (bool) {
        return super.supportsInterface(interfaceId);
    }
    // 在这里判断
    function setBaseURI(string calldata _baseURI) public auth(GLOBAL_ROLE){
        // todo something
    }
    function addAuth(address account) public{
        grantRole(GLOBAL_ROLE, account);
    }
    function rmAuth(address account) public auth(GLOBAL_ROLE){
        this.revokeRole(GLOBAL_ROLE, account);
    }   
}

tips

  1. 在新建 role(也就是调用 _setupRole) 的时候,如果没有设置 adminRole,这个权限就是顶级的。
  2. 调用 _setRoleAdmin(bytes32 role, bytes32 adminRole),会将role 的上级 role 设置为 adminRole
  3. 在调用 grantRole 和 revokeRole 的时候,会通过修改器 onlyRole 来判断当前账户是否拥有这个权限的 adminRole 权限。