当前位置: 首页 > article >正文

OpenZeppelin AccessControl 合约核心总结与单元测试

文章目录前言OpenZeppelin AccessControl 合约核心总结与单元测试1. AccessControl 是什么2. AccessControl 合约关键方法3. AccessControl 合约单元测试前言如果您觉得有用的话记得给博主点个赞评论收藏一键三连啊写作不易啊^ _ ^。而且听说点赞的人每天的运气都不会太差实在白嫖的话那欢迎常来啊!!!OpenZeppelin AccessControl 合约核心总结与单元测试1. AccessControl 是什么OpenZeppelin 提供 基于角色的权限控制RBAC的 合约模板用来给不同地址分配不同操作权限避免直接用 onlyOwner。AccessControl 合约主要分为 5 大模块:模块核心作用关键内容角色定义声明系统里有哪些角色内置 DEFAULT_ADMIN_ROLE默认管理员角色支持自定义角色如 ROLE_MANAGER、ROLE_NORMAL权限控制限制函数调用权限提供 onlyRole(角色) 修饰符只有拥有对应角色的地址才能调用被修饰的函数角色分配给地址授予 / 撤销角色grantRole(角色, 地址)授予角色revokeRole(角色, 地址)撤销角色角色检查验证地址是否拥有某角色hasRole(角色, 地址)返回布尔值用于权限校验角色管理管理角色的管理员权限_setRoleAdmin(角色, 管理员角色)设置某个角色的管理员getRoleAdmin(角色)查询某个角色的管理员2. AccessControl 合约关键方法下边是一个合约示例。// SPDX-License-Identifier: MIT pragma solidity ^0.8.28;// 导入OpenZeppelin的AccessControl合约importopenzeppelin/contracts/access/AccessControl.sol;// 自定义合约继承AccessControl获得所有权限功能 contract MyContract is AccessControl{//1. 定义自定义角色用keccak256生成唯一bytes32标识 bytes32 public constant ROLE_MANAGERkeccak256(ROLE_MANAGER);bytes32 public constant ROLE_NORMALkeccak256(ROLE_NORMAL);//2. 构造函数部署时给部署者授予最高管理员权限constructor(){_grantRole(DEFAULT_ADMIN_ROLE, _msgSender());}//3. 角色管理函数只有DEFAULT_ADMIN_ROLE能调用 // 功能将ROLE_NORMAL的管理员设置为ROLE_MANAGERfunctionsetRoleAdmin()external onlyRole(DEFAULT_ADMIN_ROLE){_setRoleAdmin(ROLE_NORMAL, ROLE_MANAGER);}//4. 权限控制函数只有ROLE_NORMAL能调用functionnormalThing()external onlyRole(ROLE_NORMAL){// 业务逻辑}//5. 权限控制函数只有ROLE_MANAGER能调用functionspecialThing()external onlyRole(ROLE_MANAGER){// 业务逻辑}}继承AccessControl类后会出现一些AccessControl的默认方法。这些都是 OpenZeppelin AccessControl 合约的内置公共 / 外部函数。角色分配与撤销类方法名参数作用grantRolebytes32 role, address account授予角色只有该角色的管理员才能调用给指定地址 account 分配 role 权限revokeRolebytes32 role, address account撤销角色只有该角色的管理员才能调用收回指定地址 account 的 role 权限renounceRolebytes32 role, address callerConfirmation主动放弃角色调用者必须是 callerConfirmation 地址主动放弃自己的 role 权限用于安全退出角色查询与管理类:方法名参数作用hasRolebytes32 role, address account检查权限返回布尔值判断 account 是否拥有 role 权限getRoleAdminbytes32 role查询管理员角色返回管理 role 的上级角色比如 ROLE_NORMAL 的管理员是 ROLE_MANAGERsupportsInterfacebytes4 interfaceId接口检查EIP-165 标准用来验证合约是否实现了某个接口AccessControl 实现了权限管理接口其中onlyRole(ROLE_NORMAL) 是 AccessControl 提供的权限修饰符用来限制函数调用者。3. AccessControl 合约单元测试版本:技术:solidity ^0.8.28、hardhat 2.28.4、openzeppelin 5.6.1 ethers 6.16.0测试用例:核心用例1验证部署者默认拥有最高权限DEFAULT_ADMIN_ROLE;核心用例2验证角色授予/检查功能正常deployer给manager授ROLE_MANAGER;核心用例3验证角色管理员设置生效ROLE_MANAGER可给他人授ROLE_NORMAL;边界用例1无权限账户无法调用受保护函数noRoleUser调用normalThing;边界用例2普通角色无法调用管理员角色的受保护函数normalUser调用specialThing;边界用例3非默认管理员无法修改角色管理员配置manager调用setRoleAdmin;边界用例4角色撤销功能生效撤销后无法调用受保护函数;源码:import{expect}fromchai;importnomicfoundation/hardhat-chai-matchers;import{ethers}fromhardhat;import{SignerWithAddress}fromnomicfoundation/hardhat-ethers/signers;// 声明合约中自定义的角色和你的Solidity合约角色名保持一致 const ROLE_MANAGERethers.keccak256(ethers.toUtf8Bytes(ROLE_MANAGER));const ROLE_NORMALethers.keccak256(ethers.toUtf8Bytes(ROLE_NORMAL));// 内置默认管理员角色AccessControl 原生常量 const DEFAULT_ADMIN_ROLEethers.ZeroHash;describe(MyAccessControlContract,function(){// 全局测试变量复用any类型对齐原示例letmyContract: any;// 合约部署者默认拥有DEFAULT_ADMIN_ROLEletdeployer: SignerWithAddress;// 测试用账户管理员角色、普通角色、无权限角色letmanager: SignerWithAddress;letnormalUser: SignerWithAddress;letnoRoleUser: SignerWithAddress;// 前置钩子每个用例执行前初始化合约账户对齐原示例beforeEach beforeEach(asyncfunction(){// 获取Hardhat本地测试账户按用途分配[deployer, manager, normalUser, noRoleUser]await ethers.getSigners()as SignerWithAddress[];// 部署合约完全对齐原示例的工厂部署写法 const MyContractFactoryawait ethers.getContractFactory(MyAccessControlContract);myContractawait MyContractFactory.deploy();await myContract.waitForDeployment();// 等待上链生效 // 公共权限初始化部署者给manager授ROLE_MANAGER再设置ROLE_NORMAL的管理员为ROLE_MANAGER await myContract.grantRole(ROLE_MANAGER, manager.address);await myContract.setRoleAdmin();// 调用合约内的角色管理员设置方法});// 核心用例1验证部署者默认拥有最高权限DEFAULT_ADMIN_ROLE it(should make deployer own DEFAULT_ADMIN_ROLE by default, asyncfunction(){const hasAdminRoleawait myContract.hasRole(DEFAULT_ADMIN_ROLE, deployer.address);expect(hasAdminRole).to.be.true;});// 核心用例2验证角色授予/检查功能正常deployer给manager授ROLE_MANAGER it(should grant ROLE_MANAGER to target address successfully, asyncfunction(){const hasManagerRoleawait myContract.hasRole(ROLE_MANAGER, manager.address);expect(hasManagerRole).to.be.true;});// 核心用例3角色管理员设置生效ROLE_MANAGER可给他人授ROLE_NORMAL it(should allow ROLE_MANAGER to grant ROLE_NORMAL, asyncfunction(){// 用manager账户调用合约原示例签名风格的账户切换 await myContract.connect(manager).grantRole(ROLE_NORMAL, normalUser.address);const hasNormalRoleawait myContract.hasRole(ROLE_NORMAL, normalUser.address);expect(hasNormalRole).to.be.true;});// 边界用例1无权限账户无法调用受保护函数noRoleUser调用normalThing it(should reject no-role user to call ROLE_NORMAL protected function, asyncfunction(){// 断言调用会被revertAccessControl 原生的权限校验失败回滚 await expect(myContract.connect(noRoleUser).normalThing()).to.be.revertedWithCustomError(myContract,AccessControlUnauthorizedAccount).withArgs(noRoleUser.address, ROLE_NORMAL);});// 边界用例2普通角色调用管理员角色的受保护函数normalUser调用specialThing it(should reject ROLE_NORMAL user to call ROLE_MANAGER protected function, asyncfunction(){// 先给normalUser授普通角色 await myContract.connect(manager).grantRole(ROLE_NORMAL, normalUser.address);// 断言调用失败 await expect(myContract.connect(normalUser).specialThing()).to.be.revertedWithCustomError(myContract,AccessControlUnauthorizedAccount).withArgs(normalUser.address, ROLE_MANAGER);});// 边界用例3非默认管理员无法修改角色管理员配置manager调用setRoleAdmin it(should reject non-DEFAULT_ADMIN to call setRoleAdmin, asyncfunction(){await expect(myContract.connect(manager).setRoleAdmin()).to.be.revertedWithCustomError(myContract,AccessControlUnauthorizedAccount).withArgs(manager.address, DEFAULT_ADMIN_ROLE);});// 边界用例4角色撤销功能生效撤销后无法调用受保护函数 it(should revoke role and reject protected function call, asyncfunction(){// 授予角色→验证可调用→撤销角色→验证不可调用 await myContract.connect(manager).grantRole(ROLE_NORMAL, normalUser.address);expect(await myContract.hasRole(ROLE_NORMAL, normalUser.address)).to.be.true;// 关键修改用ROLE_MANAGERmanager账户撤销而非deployer await myContract.connect(manager).revokeRole(ROLE_NORMAL, normalUser.address);await expect(myContract.connect(normalUser).normalThing()).to.be.revertedWithCustomError(myContract,AccessControlUnauthorizedAccount).withArgs(normalUser.address, ROLE_NORMAL);});});测试:npx hardhattesttest/MyAccessControlContract.ts测试成功!!!

相关文章:

OpenZeppelin AccessControl 合约核心总结与单元测试

文章目录前言OpenZeppelin AccessControl 合约核心总结与单元测试1. AccessControl 是什么2. AccessControl 合约关键方法3. AccessControl 合约单元测试前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊…...

Ethers 加签 + Solidity 合约验签实现 单元测试 demo

文章目录前言Ethers 加签 Solidity 合约验签实现 单元测试 demo1. 使用场景2. solidity 合约编写验签合约,签名通过ethers进行加签3. 单元测试范围4. 源码及测试前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊&a…...

SpringBoot 配置文件核心用法(Properties YAML)

SpringBoot 配置文件作用 SpringBoot 定义了规范的配置文件格式,用于集成其他框架,并集中管理项目各类配置信息,典型场景包括: 项目启动端口:自定义服务监听端口数据库连接信息:包含用户名、密码等第三方…...

什么是原型链(Prototype Chain)?proto和prototype的关系与区别是什么?

一、定义原型链是 JavaScript 实现继承和属性查找的核心机制,通俗点就是 “对象自己没有某个东西,就一层层向上找别人借” 的链条__proto__:相当于一个向上查找的链条(工具)prototype(原型对象)…...

博世 HBA 液压制动辅助系统性能规范详解

本文整理自博世官方 HBA 性能规范文档(VERSION 2.0),详细拆解乘用车 ESP 系统中 HBA 液压制动辅助的核心功能、试验条件、性能要求及标定规范,适合汽车电子、底盘控制工程师参考学习。一、HBA 功能核心定义HBA(Hydraul…...

前端-小米商城静态版复刻总结

整个项目采用css与html进行实现,有一些基础的交互功能。在做项目过程中我觉得难点有以下几个地方:1.在html 中 position一般是默认,网页就会按顺序把盒子从上到下排列,盒子属于块级元素。块级元素独占一行,可以设置宽高…...

Python 全栈实战 · 第8章

网站开发入门(Flask 快速搭建网页,实战可用) 8.1 本章能学到什么? 网站开发是 Python 全栈必备技能。本章我们用最简单、最容易上手的 Flask 框架,做到: 搭建自己的网页 实现路由访问 显示文字、页面 做简单接口服务 本地运行、浏览器访问 零基础也能一次学会,不…...

不学 Python,Java 也能调大模型?15 分钟跑通第一个 AI 接口(Java 架构师的 AI 工程笔记 01)

文章目录Java 架构师的 AI 工程笔记(一):5 个概念 第一次跟 AI 对话理论篇一、Java 工程师为什么能搞 AI Agent二、开始写代码之前,你得搞懂这 5 个概念2.1 Token——LLM 的计费单位2.2 Prompt——你给 LLM 的指令2.3 Temperatur…...

GEE案例分析:基于Dynamic World 数据的农用地识别活跃与休耕农田

🌾 用 GEE 和 Dynamic World 识别活跃与休耕农田 在全球粮食安全与土地利用变化研究中,农田的动态监测 一直是核心议题。传统方法依赖地面调查或单一时期遥感影像,难以捕捉农田的季节性轮作和长期撂荒。如今,借助 Google Earth Engine(GEE) 和高频土地覆盖产品 Dynamic…...

洛谷 B4497:[GESP202603 二级] 数数

【题目来源】 https://www.luogu.com.cn/problem/B4497 【题目描述】 对于正整数 n,如果 n 的所有数位中包含恰好 3 个 2,Alice 会认为这个正整数是美丽的。例如,正整数 24122 中包含 3 个 2,所以 24122 是美丽的;正整…...

大型城市二次供水设施远程智能管理系统

随着城市化进程的加快,二次供水设施作为城市供水“最后一公里”的关键环节,其智能化管理水平直接关系到居民的用水安全和生活质量。映翰通网络依托其IG900边缘计算网关,助力大型城市实现二次供水设施的远程智能管理,推动供水系统向…...

Java后端开发 笔试知识点复习(一)

某行某费 线上笔试一、选择题和简答题1. CompletableFuture是Java 8 引入的异步编程工具&#xff0c;用于异步任务的组合和链式调用。通过静态工厂方法可以创建CompletableFuture实例&#xff1a;CompletableFuture<String> future CompletableFuture.supplyAsync(() -…...

股票基金:欧洲各类指数都是什么意思 / 成分是什么

以下是欧洲主要指数的详细解释&#xff0c;包括市值的具体金额&#xff08;基于最新可用数据估算&#xff09;指数名称含义成分股及特点总市值&#xff08;估算&#xff09;英国富时100指数&#xff08;FTSE 100&#xff09;反映伦敦证券交易所市值最大的100家上市公司的整体表…...

Java程序设计(第3版)——配置环境变量之path

配置环境变量之path PATH的配置 以下载到C盘为例 首先点击“此电脑”&#xff08;如下所示&#xff09;&#xff1a; 此电脑 > 本地磁盘 (C:) > Program Files > Java > jdk1.8.0_131 > bin > 其次点击窗口栏右侧并复制以完成下一步配置环境的准备工作 然…...

股票基金:全球各类指数都是什么意思 / 成分是什么

A股指数指数名称含义成分股特点上证指数反映上海证券交易所上市股票价格的整体表现上海证券交易所全部A股和B股历史悠久&#xff0c;市场认可度高&#xff0c;是反映中国股市整体走势的重要指标深圳指数&#xff08;深证成指&#xff09;反映深圳证券交易所上市股票价格的整体表…...

什么是 MCP?Model Context Protocol 深度解析

什么是 MCP&#xff1f;Model Context Protocol 深度解析 一、MCP 是什么&#xff1f; MCP&#xff08;Model Context Protocol&#xff09;是 Anthropic 推出的标准化工具调用协议&#xff0c;为 AI 模型与外部工具之间的交互提供了统一的规范。简单来说&#xff0c;MCP 就像…...

07. Capture 中 Find 的高阶小应用_正则表达式 I OrCAD X Capture CIS 设计小诀窍第三季

大家好&#xff01;在进行原理图设计时&#xff0c;我们经常需要查找特定的网络信号——比如所有的TF Card数据线、所有的MCU控制信号&#xff0c;或者所有以“SW”开头的网络。如果只靠普通的字符串搜索&#xff0c;要么搜不全&#xff0c;要么把无关信号也搜出来&#xff0c;…...

浅聊Flink的广播模式

浅聊Flink的广播模式 前言 最近接触到一个新颖的中间件 Flink,为什么接触到这个呢,是因为我们公司系统需要做一个告警模块,负责采集到的监控数据会直接往 kafka 里塞,然后告警这边需要从 kafka topic 里面实时读取到监控数据,并将读取到的监控数据做一些 聚合/转换/计算…...

HarmonyOS6 ArkTS 外描边(outline)使用文档

文章目录一、核心属性与接口1. 统一设置接口 outlineAPI 11API 182. 分设属性&#xff08;精细控制&#xff09;二、OutlineStyle 枚举&#xff08;三种线型&#xff09;三、使用方式方式1&#xff1a;独立属性分开设置方式2&#xff1a;统一 outline 对象配置方式3&#xff1a…...

在中国读者中,哪些科幻小说是畅销的?为什么它们畅销

如果只从小说内容本身出发&#xff0c;而不去谈产业、政策、影视改编和时代环境&#xff0c;那么一部科幻小说能不能畅销&#xff0c;核心往往不复杂。读者真正会为一本科幻小说买单&#xff0c;通常不是因为它属于“科幻”这个门类&#xff0c;而是因为它在阅读过程中提供了几…...

金仓数据库在MySQL迁移中的技术观察:高兼容性与平滑替代路径实践

金仓数据库在MySQL迁移中的技术观察&#xff1a;高兼容性与平滑替代路径实践 2023年底&#xff0c;MySQL 5.7正式停止官方维护支持——这一曾被广泛应用于中小企业核心系统的开源数据库&#xff0c;悄然进入生命周期尾声。对开发者而言&#xff0c;这不仅是版本迭代的常规提示…...

属电子信息类专业电子信息工程(Electronic Information Engineering,简称 EE)专业是什么?

属电子信息类专业电子信息工程&#xff08;Electronic Information Engineering&#xff0c;简称 EE&#xff09;专业是什么&#xff1f;电子信息工程&#xff08;Electronic Information Engineering&#xff0c;简称 EE&#xff09;简称电子信息&#xff0c;是现代科技领域的…...

金仓数据库在MySQL迁移中的实践复盘:一家三甲医院电子病历系统性能与成本优化实录

金仓数据库在MySQL迁移中的实践复盘&#xff1a;一家三甲医院电子病历系统性能与成本优化实录 2024年初&#xff0c;西安市第一医院信息科主任老张盯着监控大屏皱眉&#xff1a;“早高峰挂号排队超3分钟&#xff0c;电子病历调阅平均要4.7秒——这哪是‘智慧医院’&#xff0c…...

YOLO系列算法改进 | 主干改进篇 | 替换SHViT高效视觉变换器 | 助力模型极致轻量化,同时保持高精度性能! | CVPR 2024

0. 前言 本文介绍了SHViT高效视觉变换器,并将其集成到ultralytics最新发布的YOLO26目标检测算法中,替换原有Backbone网络。SHViT的创新在于从宏观和微观两个层面系统性消除计算冗余,通过大步长块化主干和单头部分通道注意力,以最少的内存访问成本实现超快视觉推理。将其作…...

StressTheGPU v1.44 丨便携显卡压力测试工具

StressTheGPU v1.44 便携版是轻量免安装的专业显卡压力测试工具&#xff0c;适配 Windows 全系列系统&#xff0c;凭借低 CPU 占用的优势&#xff0c;可在极端负载下精准评估显卡稳定性与性能&#xff0c;支持实时监控与基准测试&#xff0c;全面满足硬件验机、调试等核心需求。…...

基于DQ轴谐波提取器的PMSM永磁同步电机谐波抑制技术:五七次谐波的有效抑制与电流环解耦补偿应用

基于DQ轴谐波提取器的永磁同步电机谐波抑制 PMSM 1.通过谐波提取器&#xff0c;直接提取DQ轴的谐波分量进行抑制&#xff0c;对五七次谐波电流抑制效果效果很好。 2.为了放大效果&#xff0c;采用主动注入谐波电压的方法&#xff0c;增大了电机中的谐波分量。 3.调制算法采用SV…...

HoRain云--Dash 简介

&#x1f3ac; HoRain 云小助手&#xff1a;个人主页 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站&#xff0c;性价比超高&#xff0c;大内存超划算&#xff01;忍不住分享一下给大家。点击跳转到网站。 目录 ⛳️ 推荐 …...

Node.js - 04:MongoDB、会话控制

MongoDB1、简介MongoDB 是一个基于分布式文件存储的数据库&#xff0c;官方地址 https://www.mongodb.com/数据库&#xff08;DataBase&#xff09;是按照数据结构来组织、存储和管理数据的 应用程序数据库的主要作用就是 管理数据 &#xff0c;对数据进行 增&#xff08;c&…...

大模型工具使用

介绍模型下载API测试本地平台搭建对比表格详细说明TransformersFastChatOllamavLLM关键差异介绍大模型一些简单的使用 模型下载 模型快捷的下载 魔搭社区 Ollama【可以直接在Ollama软件中下载】 API测试 通过API测试的平台&#xff1a;硅基流动 本地平台搭建 对比表格 工…...

AI辅助开发:前端“加速器”还是后端“稳定器”?——基于项目类型与用户规模的实战指南

文章目录前言一、技术原理解析1. 核心差异维度对比2. AI 辅助开发的技术架构模型二、按 DAU 规模分层的实战策略与代码实证1. 低 DAU 项目&#xff08;<1万&#xff09;&#xff1a;MVP 验证期后端实战&#xff1a;从需求到接口的秒级响应前端实战&#xff1a;快速但粗糙的 …...