什么是 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
- 在新建 role(也就是调用 _setupRole) 的时候,如果没有设置 adminRole,这个权限就是顶级的。
- 调用 _setRoleAdmin(bytes32 role, bytes32 adminRole),会将role 的上级 role 设置为 adminRole
- 在调用 grantRole 和 revokeRole 的时候,会通过修改器 onlyRole 来判断当前账户是否拥有这个权限的 adminRole 权限。