Michael.W基于Foundry精读Openzeppelin第36期——Ownable2Step.sol

news2024/11/25 13:02:11

Michael.W基于Foundry精读Openzeppelin第36期——Ownable2Step.sol

      • 0. 版本
        • 0.1 Ownable2Step.sol
      • 1. 目标合约
      • 2. 代码精读
        • 2.1 pendingOwner() && transferOwnership(address newOwner) && _transferOwnership(address newOwner)
        • 2.2 acceptOwnership()

0. 版本

[openzeppelin]:v4.8.3,[forge-std]:v1.5.6

0.1 Ownable2Step.sol

Github: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.3/contracts/access/Ownable2Step.sol

Ownable2Step库是Ownable库的拓展版本。其提供的访问权限机制同Ownable完全一致,只是owner的更换机制从由原owner直接指定(一次交互)变成原owner指定 + 新owner确认(两次交互)。Ownable2Step库具有Ownable库所有的功能函数。

1. 目标合约

继承Ownable2Step成为一个可调用合约:

Github: https://github.com/RevelationOfTuring/foundry-openzeppelin-contracts/blob/master/src/access/MockOwnable2Step.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "openzeppelin-contracts/contracts/access/Ownable2Step.sol";

contract MockOwnable2Step is Ownable2Step {
    uint public i;

    function transferOwnershipInternal(address newOwner) external {
        _transferOwnership(newOwner);
    }

    function setI(uint value) external onlyOwner {
        i = value;
    }
}

全部foundry测试合约:

Github: https://github.com/RevelationOfTuring/foundry-openzeppelin-contracts/blob/master/test/access/Ownable2Step.t.sol

2. 代码精读

2.1 pendingOwner() && transferOwnership(address newOwner) && _transferOwnership(address newOwner)
  • pendingOwner():返回当前合约处于待确认状态的owner地址;
  • transferOwnership(address newOwner):合约当前owner指定新的owner(步骤一),该操作会覆盖之前设置的_pendingOwner。注: 该函数重写了Ownerable库的transferOwnership函数;
  • _transferOwnership(address newOwner):转移本合约owner身份给一个新的地址。注:该函数重写了Ownerable库的_transferOwnership函数且不具有对访问权限的限制;
	// 处于待确认状态的owner地址
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    function pendingOwner() public view virtual returns (address) {
    	// 返回状态变量_pendingOwner
        return _pendingOwner;
    }
    
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        // 新owner地址处于待确认状态,写入状态变量_pendingOwner
        _pendingOwner = newOwner;
        // 抛出event
        emit OwnershipTransferStarted(owner(), newOwner);
    }
    
    function _transferOwnership(address newOwner) internal virtual override {
        // 清空状态变量_pendingOwner
        delete _pendingOwner;
        // 调用Ownerable.transferOwnership()进行owner身份的转移
        super._transferOwnership(newOwner);
    }

foundry代码验证

contract Ownable2StepTest is Test {
    MockOwnable2Step private _testing;

    function setUp() external {
        _testing = new MockOwnable2Step();
    }

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    function test_TransferOwnership() external {
        // test for public function: transferOwnership
        assertEq(address(0), _testing.pendingOwner());
        // case 1: pass
        vm.expectEmit(true, true, false, false, address(_testing));
        emit OwnershipTransferStarted(address(this), address(1024));
        _testing.transferOwnership(address(1024));
        assertEq(address(1024), _testing.pendingOwner());

        // test for internal function: _transferOwnership
        // case 1: pass with clearing pending owner and new owner transferred
        vm.expectEmit(true, true, false, false, address(_testing));
        emit OwnershipTransferred(address(this), address(2048));
        _testing.transferOwnershipInternal(address(2048));
        // new owner transferred
        assertEq(address(2048), _testing.owner());
        // clear the pending owner
        assertEq(address(0), _testing.pendingOwner());
    }
}
2.2 acceptOwnership()

新owner确认owner身份的转移(步骤二)。

    function acceptOwnership() external {
        address sender = _msgSender();
        // 确认本次调用者为处于待确认状态的owner地址,否则revert
        require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
        // 将owner身份转移给本次调用者(即处于待确认状态的owner地址)
        _transferOwnership(sender);
    }

foundry代码验证

contract Ownable2StepTest is Test {
    MockOwnable2Step private _testing;

    function setUp() external {
        _testing = new MockOwnable2Step();
    }

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    function test_AcceptOwnership() external {
        // case 1: pass
        _testing.transferOwnership(address(1024));
        assertEq(address(1024), _testing.pendingOwner());
        assertEq(address(this), _testing.owner());
        vm.prank(address(1024));
        vm.expectEmit(true, true, false, false, address(_testing));
        emit OwnershipTransferred(address(this), address(1024));
        _testing.acceptOwnership();
        // clear the pending owner
        assertEq(address(0), _testing.pendingOwner());
        // new owner transferred
        assertEq(address(1024), _testing.owner());

        // case 2: revert if _msgSender() is not pending owner
        // current pending owner is address(0)
        vm.expectRevert("Ownable2Step: caller is not the new owner");
        vm.prank(address(1));
        _testing.acceptOwnership();
    }
    
    function test_OnlyOwner() external {
        assertEq(address(this), _testing.owner());

        // test for modifier: onlyOwner
        // case 1: pass the check of modifier
        assertEq(0, _testing.i());
        _testing.setI(1024);
        assertEq(1024, _testing.i());
        // case 2: revert if the msgSender() is not owner
        vm.prank(address(1024));
        vm.expectRevert("Ownable: caller is not the owner");
        _testing.setI(1024);
    }
}

ps:
本人热爱图灵,热爱中本聪,热爱V神。
以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。
同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下!
如果需要转发,麻烦注明作者。十分感谢!

在这里插入图片描述

公众号名称:后现代泼痞浪漫主义奠基人

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1029540.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv8快速复现 训练 SCB-Dataset3-S 官网版本 ultralytics

目录 0 相关资料SCB-Dataset3-S 数据训练yaml文件 YOLOv8 训练SCB-Dataset3-S相关参数 0 相关资料 YOLOV8环境安装教程.:https://www.bilibili.com/video/BV1dG4y1c7dH/ YOLOV8保姆级教学视频:https://www.bilibili.com/video/BV1qd4y1L7aX/ b站视频:…

第一百五十回 自定义组件综合示例:游戏摇杆

文章目录 概念介绍实现方法示例代码我们在上一章回中介绍了自定义组件相关的内容,本章回中将综合使用这些内容 自定义游戏摇杆组件.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们介绍的游戏摇杆就是一个内层的小圆嵌套一个外层的大圆,大圆的位置不变,小圆只能在大圆…

【AD9361】设置带宽

接收链路滤波器 RX TIA LPF:RX TIA LPF 是一款单极点低通滤波器,具有可编程 3dB 转角频率。转折频率可在 1 MHz 至 70 MHz 范围内进行编程。RX TIA LPF 通常校准为基带通道带宽的 2.5 倍。 RX BB LPF:RX BB LPF 是具有可编程 3dB 转角频率的…

2、Window上的 虚拟机端口 暴露到 宿主机局域网教程

今天在公司的服务器主机上捣鼓虚拟机,要在虚拟机上安装一个oracle,虚拟机和主机能互相ping通的前提下,要将虚拟机上的端口号暴露在主机上,让项目组内的所有员工的电脑都能访问到该oracle数据库。 也就是电脑A 访问主机&#xff0…

Linux -- 使用多张gpu卡进行深度学习任务(以tensorflow为例)

在linux系统上进行多gpu卡的深度学习任务 确保已安装最新的 TensorFlow GPU 版本。 import tensorflow as tf print("Num GPUs Available: ", len(tf.config.list_physical_devices(GPU)))1、确保你已经正确安装了tensorflow和相关的GPU驱动,这里可以通…

Scala 高阶:Scala中的模式匹配

一、概述 Scala中的模式匹配(case)类似于Java中的switch...case,但是Scala的模式匹配功能更为强大。通过模式匹配,可以匹配更复杂的条件和数据结构,包括常量、类型、集合、元组等。而 Java 的 switch 语句只能用于匹配…

字符串函数----篇章(1)

目录 补上章缺失的两道题 七.笔试题(7) 八.笔试题(8) 一.字符串函数 ( 1 )----strlen函数 二.字符串函数 ( 2 )----strcpy函数 2-1模拟实现strcpy 三.字符串函数 ( 3 )----strcmp函数 ​编辑 3-1模拟实现strcmp 四.字符串函…

新建excel出现由于找不到vcruntime140_1.dll,无法继续执行代码。系统错误

打开excel报错,提示缺少​​vcruntime140_1D.dll​​。 那解决方法无疑就是找到这个​​DLL​​​,然后放到电脑系统中。 在网站​中搜索​vcruntime140_1.dll,下载 把你下载的文件放到系统中,把dll文件放到​​C:\Windows\Syst…

2、Window上的虚拟机暴露到宿主机局域网教程

今天在公司的服务器主机上捣鼓虚拟机,要在虚拟机上安装一个oracle,虚拟机和主机能互相ping通的前提下,要将虚拟机上的端口号暴露在主机上,让项目组内的所有员工的电脑都能访问到该oracle数据库。 也就是电脑A 访问主机&#xff0…

1997-2023年1月中国企业跨国并购数据Zephyr数据库

1997-2023年1月中国企业跨国并购数据 1、时间:1997-2023年1月 2、来源:根据Zephyr数据库整理形成 3、样本量:3.6万 4、指标:变量信息全面,包括交易的详细时间、金额、标的、介绍、行业等等具体如下: D…

再也不怕面试官拷打Go数据结构了!-Go语言map详解

map是Go语言中的哈希表,用来存储key/value键值对。可以在O(1)的时间复杂度内进行查找。map是Go语言在面试中经常会被问到的一个点,这篇文章就来细细梳理一下map的相关知识点,面试不再怕,offer顶呱呱。 哈希冲突 我们知道&#x…

【每日一题】74. 搜索二维矩阵

74. 搜索二维矩阵 - 力扣(LeetCode) 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非递减顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返…

探索 Java JDK 21 的新特性:一场深度解析之旅

探索 Java JDK 21 的新特性:一场深度解析之旅 探索 Java JDK 21 的新特性:一场深度解析之旅摘要 🚀引言 🌐正文 📚新特性概览 🆕1. 模式匹配的魅力 🧩2. 记录类型:轻松管理数据 &…

【深度学习】ONNX模型多线程快速部署【基础】

【深度学习】ONNX模型CPU多线程快速部署【基础】 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】ONNX模型CPU多线程快速部署【基础】前言搭建打包环境python多线程并发简单教程基本教程ONNX模型多线程并发 打包成可执行文件总结 前…

王道考研计算机组成原理

王道考研计算机组成原理 计算机系统概述计算机系统层次结构计算机的性能指标错题 数据的表示和运算数制与编码运算方法和运算电路浮点数的表示与运算 存储系统存储器概述主存储器主存储器与CPU的连接外部存储器高速缓冲存储器虚拟存储器 指令系统指令格式指令的寻址方式程序的机…

js加密双重保障之sm2国密

前言 ​ 最近看到一些项目里边有用到sm2/3/4国密加密算法,这里给大家简单介绍一下。 知识科普 SM2(国密算法)是一种非对称加密算法,由中国国家密码管理局(NCC)制定,并被广泛应用于中国的信息…

9月21日作业

登录代码&#xff1a; widget.h #ifndef REGISTER_H #define REGISTER_H#include <QWidget> #include <QDebug> #include <QSqlDatabase> #include <QSqlQuery> #include <QMessageBox>namespace Ui { class Register; }class Register : publ…

selenium自动化测试-获取动态页面小说

有的网站页面是动态加载的资源&#xff0c;使用bs4库只能获取静态页面内容&#xff0c;无法获取动态页面内容&#xff0c;通过selenium自动化测试工具可以获取动态页面内容。 参考之前的"bs4库爬取小说工具"文章代码&#xff0c;稍微修改下&#xff0c;就可以转成获…

9.21号作业

实现把注册的信息导入数据库中 second.h #ifndef SECOND_H #define SECOND_H#include <QWidget> #include <QDebug> namespace Ui { class Second; }class Second : public QWidget {Q_OBJECT public:void newslot(); public:explicit Second(QWidget *parent n…