当我们开发一个智能合约,但是里面有一些函数不能随便让别人调用,只能“拥有权限”的管理员能够调用,那么这时候我们会用到权限管理机制。

实现起来也很简单,设置一个 owner 变量,通过 modifier onlyOwner() 检查调用 onlyOwnerCanCall() 的地址是否等于预先设置好的 woner,这样就可以保证只有 owner 能够调用这个函数。

contract AccessControl {
address private owner; constructor() {
owner = msg.sender;
} modifier onlyOwner() {
require(msg.sender == owner, "Caller is not the owner");
_;
} function onlyOwnerCanCall() public onlyOwner {
// ...
}
}

由于权限控制这个机制被广泛应用在不同的场景中,为了避免重复开发以及保证实现质量,开发者可以从 openzeppelin 的标准库中使用 openzeppelin-contracts/contracts/access 目录下的标准库进行实现。

目前为 5.2.0 版本:https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.2.0/contracts/access

主要分为 3 种方案:

  1. Ownable:只要单一的 owner 权限,owner 权限可以转移,放弃(置为 0 地址)。
  2. Ownable2Step:在 Ownable 基础上避免了将 owner 权限转移到了错误的地址导致权限丢失,Ownable2Step 在权限转移这个环节,添加了接受权限的地址需要调用 acceptOwnership() 进行领取的步骤。
  3. AccessControl:不再采用单一的 owner 进行权限管理,而是更细粒度地细分到了多种权限账户。

在接下来的文章中会对 AccessControl 进行展开介绍。

AccessControl

代码实现:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.2.0/contracts/access/AccessControl.sol

AccessControl 中存储所有管理员信息的全局变量是 _roles ,其次是代表默认管理员的 DEFAULT_ADMIN_ROLE

权限检查

当需要对某个函数进行调用权限的限制时,可以通过添加 modifier onlyRole(bytes32 role) 的方式来检查 msg.sender 是否满足指定权限角色 ROLE 的要求。

function privilegedFunctions() public onlyRole(ROLE){...}

modifier onlyRole(bytes32 role) 会调用以下的函数来进行检查

modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
} function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
} function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
} function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}

当用户调用需要 ROLE 权限的函数时,modifier onlyRole(bytes32 role) 会检查 _roles[ROLE].hasRole[mag.sender] 是否为 true

权限角色管理

而当需要通过权限管理员来管理权限角色时:

  1. 通过 grantRole(bytes32 role, address account) 来授予 account 地址 role 权限角色。
  2. 通过 revokeRole(bytes32 role, address account) 来移除 account 地址 role 权限角色。
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
} function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
} function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
} function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
} function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}

当需要添加 ROLE 的权限时,则需要通过 onlyRole(getRoleAdmin(role) 检查 _roles[_roles[role].adminRole].hasRole[mag.sender] 是否为 true。也就是说每一个权限角色(ROLE)的管理员,都是对应着另一个权限角色(ROLE_ADMIN)。

默认管理员

那么权限角色有管理员,管理员还有他自己的管理员,那岂不是无穷尽也?这个时候就用到 DEFAULT_ADMIN_ROLE 角色了,由于它的值被设定为 0x00,所以只要你不为某一个权限角色设置 adminRole,那么 adminRole 的值就会指向 DEFAULT_ADMIN_ROLE(0x00)

应用实例

根据上面的内容,实现了一个简单的 Demo 协助读者理解(仅供参考,请勿用作生产代码)。

contract RoleDemo is AccessControl {
// Define roles
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); constructor() {
// Grant DEFAULT_ADMIN_ROLE to contract deployer
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
// Grant ADMIN_ROLE to contract deployer
_grantRole(ADMIN_ROLE, address(0x01));
// Grant MINTER_ROLE to contract deployer
_grantRole(MINTER_ROLE, address(0x02)); // Set ADMIN_ROLE as the admin role for MINTER_ROLE
_setRoleAdmin(MINTER_ROLE, ADMIN_ROLE);
} // Function can only be called by addresses with DEFAULT_ADMIN_ROLE
function defultAdminFunction() public onlyRole(DEFAULT_ADMIN_ROLE) {
// Default admin function implementation
} // Function can only be called by addresses with ADMIN_ROLE
function adminFunction() public onlyRole(ADMIN_ROLE) {
// Admin function implementation
} // Function can only be called by addresses with MINTER_ROLE
function minterFunction() public onlyRole(MINTER_ROLE) {
// Minter function implementation
}
}

这段代码实现了以下的功能:

  1. 设置默认管理员 DEFAULT_ADMIN_ROLE 为合约部署者 deployer
  2. 设置 address(0x02)MINTER_ROLE 权限角色
  3. 设置 address(0x01)MINTER_ROLE 权限的管理员 ADMIN_ROLE,可以移除或添加 MINTER_ROLE 权限角色。
  4. DEFAULT_ADMIN_ROLE 默认作为 ADMIN_ROLE 的管理员,可以移除或添加 ADMIN_ROLE 权限角色。

【技术分析】简单了解 AccessControl的更多相关文章

  1. 蓝牙协议分析(7)_BLE连接有关的技术分析

    转自:http://www.wowotech.net/bluetooth/ble_connection.html#comments 1. 前言 了解蓝牙的人都知道,在经典蓝牙中,保持连接(Connec ...

  2. iOS直播的技术分析与实现

    HTTP Live Streaming直播(iOS直播)技术分析与实现 发布于:2014-05-28 13:30阅读数:12004 HTTP Live Streaming直播(iOS直播)技术分析与实 ...

  3. 横向技术分析C#、C++和Java优劣

    转自横向技术分析C#.C++和Java优劣 C#诞生之日起,关于C#与Java之间的论战便此起彼伏,至今不辍.抛却Microsoft与Sun之间的恩怨与口角,客观地从技术上讲,C#与Java都是对传统 ...

  4. 美链BEC合约漏洞技术分析

    这两天币圈链圈被美链BEC智能合约的漏洞导致代币价值几乎归零的事件刷遍朋友圈.这篇文章就来分析下BEC智能合约的漏洞 漏洞攻击交易 我们先来还原下攻击交易,这个交易可以在这个链接查询到. 我截图给大家 ...

  5. 【Python量化投资】基于技术分析研究股票市场

    一 金融专业人士以及对金融感兴趣的业余人士感兴趣的一类就是历史价格进行的技术分析.维基百科中定义如下,金融学中,技术分析是通过对过去市场数据(主要是价格和成交量)的研究预测价格方向的证券分析方法. 下 ...

  6. [IC]Lithograph(1)光刻技术分析与展望

    文章主体转载自: 1.zol摩尔定律全靠它 CPU光刻技术分析与展望 2.wiki:Extreme ultraviolet lithography 3.ITRS 2012 1. 光刻技术组成和关键点 ...

  7. 转: HTTP Live Streaming直播(iOS直播)技术分析与实现

    http://www.cnblogs.com/haibindev/archive/2013/01/30/2880764.html HTTP Live Streaming直播(iOS直播)技术分析与实现 ...

  8. Fabric 和 Sawtooth 技术分析(下)

    http://blog.talkingdata.com/?p=6172 在前一篇文章(Fabric和Sawtooth技术分析(上))中,我们着重跟大家分享了 Fabric 相关的内容,在本篇文章中,我 ...

  9. 【转】HTTP Live Streaming直播(iOS直播)技术分析与实现

    HTTP Live Streaming直播(iOS直播)技术分析与实现 不经意间发现,大半年没写博客了,自觉汗颜.实则2012后半年,家中的事一样接着一样发生,实在是没有时间.快过年了,总算忙里偷闲, ...

  10. Ripple 20:Treck TCP/IP协议漏洞技术分析

    本文由“合天智汇”公众号首发,作者:b1ngo Ripple 20:Treck TCP/IP协议漏洞技术分析 Ripple20是一系列影响数亿台设备的0day(19个),是JSOF研究实验室在Trec ...

随机推荐

  1. 即时通讯技术文集(第35期):IM群聊技术合集(Part2) [共12篇]

    为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第35 期. ​[- 1 -] 直播系统聊天技术(一):百万在线的美拍直播弹幕系统的实时推送技术 ...

  2. 万字长文:手把手教你实现一套高效的IM长连接自适应心跳保活机制

    本文作者"Carson",现就职于腾讯公司,原题"高效保活长连接:手把手教你实现自适应的心跳保活机制",有较多修订和改动. 1.引言 当要实现IM即时通讯聊天. ...

  3. 在 Vercel 部署随机图 API

    在本文中,将详细介绍如何在 Vercel 平台上部署一个具有分类功能的随机图片 API.通过这个 API,用户可以根据不同的分类获取随机图片链接,并且还可以从所有分类中随机获取一张图片. 项目结构 首 ...

  4. 记录下uniapp的请求封装

    请求封装就是经常见的事但是从来没有记录过,今天来记录一下简单的封装 首先封装自己的域名,可以和封装写在一起,但是最好单独写一个独立的js文件 这边就以一个域名为例 let baseUrl='域名地址' ...

  5. linux 手动释放内存

    在 Linux 系统中,内存管理通常由系统自动处理,但在某些情况下,手动释放内存可能是必要的.例如,当业务应用比较繁忙时会频繁存取文件,物理内存会被缓存大量占用,有时会出现内存不足的情况发生,甚至会导 ...

  6. 权限对象:B_BUP_PCPT

    权限对象:B_BUP_PCPT 事务代码: BUPA_PRE_EOP CVP_PRE_EOP(需要SFW5激活SAP Information Lifecycle Management,事务码IRMPO ...

  7. WordPress产品导入后内容出现乱码,以及附属一些别的功能

    效果图如下 该插件附带了一个可以把产品描述里面的超链接给去掉,以及有的产品图片点击会在地址栏上面显示图片的路径,在该插件可以进行关闭,并且替换成一个模态窗,还有对产品邮费展示进行了处理,到金额到达包邮 ...

  8. 硬件设计:电路防护--TVS管

    参考资料:TVS参数及选型方法 TVS参数理解 深圳市硕凯电子有限公司元器件产品说明 TVS(Transient Voltage suppressor)或称瞬变电压抑制二极管.当TVS管两端经受瞬间的 ...

  9. linux安装flink

    参考链接https://blog.csdn.net/boling_cavalry/article/details/85038527   1.下载flink 在Flink官网下载,地址是:https:/ ...

  10. 鸿蒙开发 - 支持导出,跨文件使用的自定义样式 AttributeModifier

    我们在自定义组件的时候,无论是用 @Styles 还是 @Extend,都很难真正做到独立的封装样式,因为这两者都不支持导出,不可以跨文件调用 这篇文章主要介绍一个接口 AttributeModifi ...