Openzeppelin学习记录

  • Openzeppelin学习记录
    • 模块结构
    • 1. access
      • 1.1 AccessControl.sol
      • 1.2 AccessControlEnumerable.sol
      • 1.3 Ownable.sol

Openzeppelin学习记录

OpenZeppelin的智能合约代码库是以太坊开发者的宝库,OpenZeppelin代码库包含了经过社区审查的ERC代币标准、安全协议以及很多的辅助工具库,这些代码可以帮助开发者专注业务逻辑的,而无需重新发明轮子。

基于OpenZeppelin开发合约,即可以提高代码的安全性,又可以提高开发效率。(这两段话抄的登链社区哈哈哈)

本文只记录学习过程中的的一些想法和问题,目前没有实操。

本人英文文档阅读能力有限,这也是第一次尝试阅读英文文档(之前都是看的中文版,但这次搜到的都太老了,solidity还在用0.4+的版本~),如有错误欢迎大家批评指正!

模块结构

从github上下下来原始合约,目录结构如图所示:

-contracts-access//主要包含拥有者管理和角色管理AccessControl.sol               //角色管理,1对1AccessControlEnumerable.sol        //角色管理,1对多Ownable.sol                        //拥有者管理-finance  -governance -interfaces-metax-mocks-proxys-security-token-utils

今天先写一下access部分的笔记

1. access

1.1 AccessControl.sol

该文件为角色管理合约:其中有两个关键角色:role和roleAdmin

合约中提供了几个函数来进行角色的转换,其中包括一些查询函数,此外还有角色转变函数,和角色改变时会触发的event.

function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool){};//(没太懂)
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)){};
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)){};
function renounceRole(bytes32 role, address account) public virtual override{};
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual{};

其中,

admin:grantRolerevokeRolerole:renounonceRole更改admin的函数(可见性是internal的,应该是在使用者自己的合约中调用)
_setRoleAdmin

具体文件如下(害怕出错,英文注释没有动,添加了一些自己理解的中文注释)

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";/*** @dev External interface of AccessControl declared to support ERC165 detection.*/
interface IAccessControl {function hasRole(bytes32 role, address account) external view returns (bool);function getRoleAdmin(bytes32 role) external view returns (bytes32);function grantRole(bytes32 role, address account) external;function revokeRole(bytes32 role, address account) external;function renounceRole(bytes32 role, address account) external;
}/*** @dev Contract module that allows children to implement role-based access* control mechanisms. This is a lightweight version that doesn't allow enumerating role* members except through off-chain means by accessing the contract event logs. Some* applications may benefit from on-chain enumerability, for those cases see* {AccessControlEnumerable}.** Roles are referred to by their `bytes32` identifier. These should be exposed* in the external API and be unique. The best way to achieve this is by* using `public constant` hash digests:** ```* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");* ```** Roles can be used to represent a set of permissions. To restrict access to a* function call, use {hasRole}:** ```* function foo() public {*     require(hasRole(MY_ROLE, msg.sender));*     ...* }* ```** Roles can be granted and revoked dynamically via the {grantRole} and* {revokeRole} functions. Each role has an associated admin role, and only* accounts that have a role's admin role can call {grantRole} and {revokeRole}.** By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means* that only accounts with this role will be able to grant or revoke other* roles. More complex role relationships can be created by using* {_setRoleAdmin}.** WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to* grant and revoke this role. Extra precautions should be taken to secure* accounts that have been granted it.*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {struct RoleData {mapping(address => bool) members;bytes32 adminRole;}mapping(bytes32 => RoleData) private _roles;bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;/*** @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`** `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite* {RoleAdminChanged} not being emitted signaling this.** _Available since v3.1._*///更改角色role管理员(0x00是所有角色的初始管理员,尽管刚开始的时候没有发出这个事件)event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);/*** @dev Emitted when `account` is granted `role`.** `sender` is the account that originated the contract call, an admin role* bearer except when using {_setupRole}.*///sender(通常是admin)授予某accounte为roleevent RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);/*** @dev Emitted when `account` is revoked `role`.** `sender` is the account that originated the contract call:*   - if using `revokeRole`, it is the admin role bearer*   - if using `renounceRole`, it is the role bearer (i.e. `account`)*///sender(通常是admin)撤销某accounte的roleevent RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);/*** @dev Modifier that checks that an account has a specific role. Reverts* with a standardized message including the required role.** The format of the revert reason is given by the following regular expression:**  /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/** _Available since v4.1._*///检查调用者是否有某角色(没有进行一些处理(回复消息告知其不是该角色))modifier onlyRole(bytes32 role) {_checkRole(role, _msgSender());_;}/*** @dev See {IERC165-supportsInterface}.*/function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);//当使用super时,调用的是继承的该函数,不是它自己}/*** @dev Returns `true` if `account` has been granted `role`.*/function hasRole(bytes32 role, address account) public view override returns (bool) {return _roles[role].members[account];}/*** @dev Revert with a standard message if `account` is missing `role`.** The format of the revert reason is given by the following regular expression:**  /^AccessControl: account (0x[0-9a-f]{20}) is missing role (0x[0-9a-f]{32})$/*/function _checkRole(bytes32 role, address account) internal view {if (!hasRole(role, account)) {revert(string(abi.encodePacked("AccessControl: account ",Strings.toHexString(uint160(account), 20)," is missing role ",Strings.toHexString(uint256(role), 32))));}}/*** @dev Returns the admin role that controls `role`. See {grantRole} and* {revokeRole}.** To change a role's admin, use {_setRoleAdmin}.*/function getRoleAdmin(bytes32 role) public view override returns (bytes32) {return _roles[role].adminRole;}/*** @dev Grants `role` to `account`.** If `account` had not been already granted `role`, emits a {RoleGranted}* event.** Requirements:** - the caller must have ``role``'s admin role.*///msg.sender= admin,授予account 的rolefunction grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {_grantRole(role, account);}/*** @dev Revokes `role` from `account`.** If `account` had been granted `role`, emits a {RoleRevoked} event.** Requirements:** - the caller must have ``role``'s admin role.*///admin撤销account 的rolefunction revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {_revokeRole(role, account);}/*** @dev Revokes `role` from the calling account.** Roles are often managed via {grantRole} and {revokeRole}: this function's* purpose is to provide a mechanism for accounts to lose their privileges* if they are compromised (such as when a trusted device is misplaced).** If the calling account had been granted `role`, emits a {RoleRevoked}* event.** Requirements:** - the caller must be `account`.*///account 主动撤销自己的角色function renounceRole(bytes32 role, address account) public virtual override {require(account == _msgSender(), "AccessControl: can only renounce roles for self");_revokeRole(role, account);}/*** @dev Grants `role` to `account`.** If `account` had not been already granted `role`, emits a {RoleGranted}* event. Note that unlike {grantRole}, this function doesn't perform any* checks on the calling account.** [WARNING]* ====* This function should only be called from the constructor when setting* up the initial roles for the system.** Using this function in any other way is effectively circumventing the admin* system imposed by {AccessControl}.* ====*/function _setupRole(bytes32 role, address account) internal virtual {_grantRole(role, account);}/*** @dev Sets `adminRole` as ``role``'s admin role.** Emits a {RoleAdminChanged} event.*/function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);_roles[role].adminRole = adminRole;}function _grantRole(bytes32 role, address account) private {if (!hasRole(role, account)) {_roles[role].members[account] = true;emit RoleGranted(role, account, _msgSender());}}function _revokeRole(bytes32 role, address account) private {if (hasRole(role, account)) {_roles[role].members[account] = false;emit RoleRevoked(role, account, _msgSender());}}
}

1.2 AccessControlEnumerable.sol

1.1 是一对一,这个是一对多,就是管理一个同为role的集合roles,大体功能是一样的,我没仔细看,把代码贴这吧

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "./AccessControl.sol";
import "../utils/structs/EnumerableSet.sol";/*** @dev External interface of AccessControlEnumerable declared to support ERC165 detection.*/
interface IAccessControlEnumerable {function getRoleMember(bytes32 role, uint256 index) external view returns (address);function getRoleMemberCount(bytes32 role) external view returns (uint256);
}/*** @dev Extension of {AccessControl} that allows enumerating the members of each role.*/
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {using EnumerableSet for EnumerableSet.AddressSet;mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;/*** @dev See {IERC165-supportsInterface}.*/function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);}/*** @dev Returns one of the accounts that have `role`. `index` must be a* value between 0 and {getRoleMemberCount}, non-inclusive.** Role bearers are not sorted in any particular way, and their ordering may* change at any point.** WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure* you perform all queries on the same block. See the following* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]* for more information.*/function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {return _roleMembers[role].at(index);}/*** @dev Returns the number of accounts that have `role`. Can be used* together with {getRoleMember} to enumerate all bearers of a role.*/function getRoleMemberCount(bytes32 role) public view override returns (uint256) {return _roleMembers[role].length();}/*** @dev Overload {grantRole} to track enumerable memberships*/function grantRole(bytes32 role, address account) public virtual override {super.grantRole(role, account);_roleMembers[role].add(account);}/*** @dev Overload {revokeRole} to track enumerable memberships*/function revokeRole(bytes32 role, address account) public virtual override {super.revokeRole(role, account);_roleMembers[role].remove(account);}/*** @dev Overload {renounceRole} to track enumerable memberships*/function renounceRole(bytes32 role, address account) public virtual override {super.renounceRole(role, account);_roleMembers[role].remove(account);}/*** @dev Overload {_setupRole} to track enumerable memberships*/function _setupRole(bytes32 role, address account) internal virtual override {super._setupRole(role, account);_roleMembers[role].add(account);}
}

1.3 Ownable.sol

该合约用的最多了,给所部署的合约设置一个拥有者,一次来约束合约中和某些操作的权限。可以称得上典中典!

// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "../utils/Context.sol";/*** @dev Contract module which provides a basic access control mechanism, where* there is an account (an owner) that can be granted exclusive access to* specific functions.** By default, the owner account will be the one that deploys the contract. This* can later be changed with {transferOwnership}.** This module is used through inheritance. It will make available the modifier* `onlyOwner`, which can be applied to your functions to restrict their use to* the owner.*默认情况下,所有者帐户将是部署合约的帐户。这以后可以用 {transferOwnership} 更改。*该模块通过继承使用。它将使修饰符可用`onlyOwner`,可以应用于您的函数以限制它们的使用者。*/abstract contract Ownable is Context {address private _owner;//拥有者身份转移event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);/*** @dev Initializes the contract setting the deployer as the initial owner.*///初始化合约,将部署者设置为初始所有者constructor() {address msgSender = _msgSender();_owner = msgSender;emit OwnershipTransferred(address(0), msgSender);}/*** @dev Returns the address of the current owner.*/function owner() public view virtual returns (address) {return _owner;}/*** @dev Throws if called by any account other than the owner.*/modifier onlyOwner() {require(owner() == _msgSender(), "Ownable: caller is not the owner");_;}/*** @dev Leaves the contract without owner. It will not be possible to call* `onlyOwner` functions anymore. Can only be called by the current owner.** NOTE: Renouncing ownership will leave the contract without an owner,* thereby removing any functionality that is only available to the owner.*///使合约没有所有者。将无法调用`onlyOwner` 不再起作用。只能由当前所有者调用。// 注意:放弃所有权将使合约没有所有者,从而删除任何仅对所有者可用的功能function renounceOwnership() public virtual onlyOwner {emit OwnershipTransferred(_owner, address(0));_owner = address(0);}/*** @dev Transfers ownership of the contract to a new account (`newOwner`).* Can only be called by the current owner.*///原拥有者将权力交接给新人(青天已死,黄天当立)function transferOwnership(address newOwner) public virtual onlyOwner {require(newOwner != address(0), "Ownable: new owner is the zero address");emit OwnershipTransferred(_owner, newOwner);_owner = newOwner;}
}

OK,access看完啦!

Openzeppelin学习记录一:access模块(AccessControl.sol+Ownable.sol)相关推荐

  1. Openzeppelin学习记录二:utils模块(SafeMath.sol+SafeCast.sol)

    Openzeppelin学习记录一:access模块(AccessControl.sol+Ownable.sol) Openzeppelin学习记录 2.Utils 2.1 Math 2.2 Safe ...

  2. STM32的学习记录--2.WiFi模块的使用

    本次学习用的单片机是STM32F103C8T6 本次学习用的WiFi模块是ESP8266 本博客仅用于课余学习,不可商用!!! 如有侵权,请告知我删除博客,谢谢配合. 以下学习资料均在云盘,仅供学习交 ...

  3. STM32学习记录——ATK-HC05蓝牙模块

    一.结构图 二.使用 大家一开始用这个模块大多应该都是看的正点原子的视频教程,但按照视频来接线,会发现lcd上一直显示ATK-HCO5 error,我也是,用串口助手试了很久都没用,后来才看到解决方式 ...

  4. 品优购项目学习记录--01公共模块制作

    文章目录 一.品优购项目规划 1.1 开发工具以及技术栈 1.1.1 开发工具 1.1.2 技术栈 1.2 品优购项目搭建工作 1.2.1 相关文件夹以及文件创建 1.2.2 模块化开发 1.2.3 ...

  5. Matlab学习记录:常用模块

    1.假如你用的2019版本,导出的模型不能用到比2019版本低的matlab软件,此时可以通过以下操作导出别的版本的文件,就可以在低版本软件下打开. 2.模型配置文件 新建一个脚本 运行完之后,在保存 ...

  6. Arduino不同测距传感器对于较小物体测距效果【学习记录】

    文章目录 前言 一.HC-SR04超声波测距模块 二.TOF200F红外激光测距模块 三.SP-TOF可见激光测距模块 总结 前言 由于最近的设计项目有对于较小物体车测距需求,所以对三种类型的测距模块 ...

  7. Python学习记录day6-反射、常用模块

    Python学习记录day6-反射.常用模块 @(学习)[python] Python学习记录day6-反射常用模块 反射 常用模块 1 sys System-specific parameters ...

  8. Harmony OS 设备开发学习记录(六)-- 通过PWM模块播放音乐

    Harmony OS 设备开发学习记录(六)-- 通过PWM模块播放音乐 基于hispark wifi套件采用harmony os 2.0全量代码 一.看原理图确定硬件电路 本例采用红绿灯扩展版上的蜂 ...

  9. 学习记录--蓝牙模块HC05(串口收发)

    主要实现:PC上位机与蓝牙之间的通信(收发) 一,HC05模式等一系列设置 参考博客: (11条消息) stm32之蓝牙模块HC-05使用_一剃解千愁的博客-CSDN博客_stm32蓝牙模块的使用 ( ...

最新文章

  1. windows7 64位机上CUDA7.0配置及在VS2010中的简单使用举例
  2. “脑补”的科学依据:眼前的黑不是黑,靠得是你的大脑
  3. 访问网络计算机的盘符,win7系统下如何禁止访问指定盘符保护电脑安全
  4. 云顶之弈机器人法爆_LOL云顶之弈机器人出装怎么选
  5. 从此,懂一点CDMA
  6. 经典排序:第k个元素(快排和双向扫描法)
  7. fatal error: gnu/stubs-32.h: No such file or directory
  8. 安卓前端和python后端_在移动应用程序中结合html前端和python“后端”
  9. springboot从OSS下载图片并打包为压缩包下载
  10. Webbrowser指定IE内核版本(更改注册表)
  11. CentOS6.5挂载大于2TB的磁盘使用parted和GPT类型
  12. 【Python】小甲鱼Python学习总结——代码版
  13. depth, bedgraph, bigwig之间的联系与区别
  14. L0范数、L1范数和L2范数的区别
  15. SEO关键词排名优化做到百度首页的核心操作
  16. JAVA的IO/NIO?
  17. 基于51单片机的温度甲烷监测报警串口上报proteus仿真原理图PCB
  18. MySQL事务的4种隔离级别
  19. 【C语言】例3.5 求方程的根
  20. 配置squid做二级代理,支持访问http和https

热门文章

  1. 无源定位入门(一):TDOA(2)原理和算法推导部分
  2. PTA - 数据库合集41
  3. 通过爬虫使用百度翻译
  4. IntelliJ IDEA 知识一网打尽
  5. Elasticsearch中的相似度评分机制
  6. OKR与CFR管理模式(二)-CFR与OKR的绩效管理
  7. cefsharp之devtools开发者工具API应用-Emulation
  8. Nginx学习笔记2--(极客时间-陶辉)
  9. 计算机网络复习——第三章数据链路层
  10. linux 异星工厂服务器,Factorio服务器部署指南