Solidity 权限控制合约

Solidity 合约中一般会有多种针对不同数据的操作,例如对于存证内容的增加、更新及查询,所以需要制定一套符合要求的权限控制。

如何对合约的权限进行划分?我们针对Solidity语言设计了一套通过地址标记的解决方案。

合约中划分了角色和账户两级权限,如下所示:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Access {
   mapping(bytes32 =>mapping(address =>bool)) public roles;

   // 0xf23ec0bb4210edd5cba85afd05127efcd2fc6a781bfed49188da1081670b22d8
   bytes32 constant private ADMIN = keccak256("admin");

   // 0xcb61ad33d3763aed2bc16c0f57ff251ac638d3d03ab7550adfd3e166c2e7adb6
   bytes32 constant private USER = keccak256("user");

   // 授权合约部署者 ADMIN 权限
   constructor() {
      _grantRole(ADMIN, msg.sender);
   }

   modifier onlyAdmin(address _account) {
      require(roles[ADMIN][_account], "not authorized");
      _;
   }

   function _grantRole(bytes32 _role, address _account) internal {
      roles[_role][_account] = true;
   }

   // 授权
   function grantRole(bytes32 _role, address _account) external onlyAdmin(_account) {
      _grantRole(_role, _account);
   }

   function _revokeRole(bytes32 _role, address _account) internal {
      roles[_role][_account] = false;
   }

   // 撤销授权
   function revokeRole(bytes32 _role, address _account) external onlyAdmin(_account) {
      _revokeRole(_role, _account);
   }
}

Solidity有一个ecrecover 指令,可以根据消息hash 和签名,返回签名者的地址:ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) ret ...