权限控制合约是一种常见的智能合约,用于限制对合约功能的访问权限,在这章011.智能合约的结构——07权限管理 有粗略介绍过。
它的语法权限控制合约的语法与普通合约的语法相似,但要使用Solidity中的修饰符来定义访问权限,
在 016.Solidity入门——03函数修饰符 和033.Solidity入门——20函数的可视范围 这两个章节有讲过。
咱们来复习下这几个常见的修饰符:
修饰符 | 描述 |
public | 定义为公共变量或函数,可以在任何地方访问。 |
private | 义为私有变量或函数,只能在合约内部访问。 |
internal | 定义为内部变量或函数,只能在合约内部或继承合约中访问。 |
external | 定义为外部函数,只能从合约外部通过交易调用。 |
这是一个简单的权限控制合约代码,包含了管理员角色和用户角色的访问权限控制,角色的添加和移除:
pragma solidity ^0.8.7;
contract AccessControl {
// 定义角色
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant USER_ROLE = keccak256("USER_ROLE");
// 定义事件
event AdminAdded(address indexed account);
event AdminRemoved(address indexed account);
event UserAdded(address indexed account);
event UserRemoved(address indexed account);
// 管理员角色
struct Admin {
bool exists;
uint256 index;
}
// 用户角色
struct User {
bool exists;
uint256 index;
}
// 所有角色的账户
address[] public admins;
address[] public users;
// 存储角色对应的账户
mapping(address => Admin) private adminAccounts;
mapping(address => User) private userAccounts;
// 仅允许管理员访问的函数
modifier onlyAdmin() {
require(isAdmin(msg.sender), "AccessControl: caller is not an admin");
_;
}
// 仅允许用户访问的函数
modifier onlyUser() {
require(isUser(msg.sender), "AccessControl: caller is not a user");
_;
}
// 添加管理员角色
function addAdmin(address account) public onlyAdmin {
require(!adminAccounts[account].exists, "AccessControl: account already has admin role");
adminAccounts[account] = Admin(true, admins.length);
admins.push(account);
emit AdminAdded(account);
}
// 移除管理员角色
function removeAdmin(address account) public onlyAdmin {
require(adminAccounts[account].exists, "AccessControl: account does not have admin role");
uint256 indexToDelete = adminAccounts[account].index;
address accountToMove = admins[admins.length - 1];
admins[indexToDelete] = accountToMove;
adminAccounts[accountToMove].index = indexToDelete;
admins.pop();
delete adminAccounts[account];
emit AdminRemoved(account);
}
// 添加用户角色
function addUser(address account) public onlyAdmin {
require(!userAccounts[account].exists, "AccessControl: account already has user role");
userAccounts[account] = User(true, users.length);
users.push(account);
emit UserAdded(account);
}
// 移除用户角色
function removeUser(address account) public onlyAdmin {
require(userAccounts[account].exists, "AccessControl: account does not have user role");
uint256 indexToDelete = userAccounts[account].index;
address accountToMove = users[users.length - 1];
users[indexToDelete] = accountToMove;
userAccounts[accountToMove].index = indexToDelete;
users.pop();
delete userAccounts[account];
emit UserRemoved(account);
}
// 检查是否是管理员账户
function isAdmin(address account) public view returns (bool) {
return adminAccounts[account].exists;
}
// 检查是否是用户账户
function isUser(address account) public view returns (bool) {
return userAccounts[account].exists;
}
}