Solidity 练习:访问控制
睡不醒的鲤鱼 2022-12-29 Web3 Solidity
# 一、题目说明
实现基于角色的访问控制。
# 二、任务列表
- 定义一个名为 USER 的新角色,使用字符串 “USER” 的 keccak256 哈希作为该角色的标识符。
- 定义一个修饰符 onlyRole(byte32 _role),在执行代码前检查 msg.sender 是否有 _role 角色。
- 完成函数 _grantRole,该函数会把 _account 的 _role 角色置为 true,并且会提交 GrantRole 事件。
- 完成函数 grantRole,该函数必须仅允许具有 ADMIN 角色的 msg.sender 的访问。
- 完成 external 函数 revokeRole,用于撤销 _account 的 _role 角色,并且会提交 RevokeRole 事件。该函数仅允许具有 ADMIN 角色的 msg.sender 的访问。
- 在合约部署时,授予 ADMIN 角色给 msg.sender。
# 三、解答代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract AccessControl {
event GrantRole(bytes32 indexed role, address indexed account);
event RevokeRole(bytes32 indexed role, address indexed account);
mapping(bytes32 => mapping(address => bool)) public roles;
bytes32 public constant ADMIN = keccak256(abi.encodePacked("ADMIN"));
bytes32 public constant USER = keccak256(abi.encodePacked("USER"));
modifier onlyRole(bytes32 _role) {
require(roles[_role][msg.sender], "not authorized");
_;
}
constructor() {
_grantRole(ADMIN, msg.sender);
}
function _grantRole(bytes32 _role, address _account) internal {
roles[_role][_account] = true;
emit GrantRole(_role, _account);
}
function grantRole(bytes32 _role, address _account)
external
onlyRole(ADMIN)
{
_grantRole(_role, _account);
}
function revokeRole(bytes32 _role, address _account)
external
onlyRole(ADMIN)
{
roles[_role][_account] = false;
emit RevokeRole(_role, _account);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41