Michael.W基于Foundry精读Openzeppelin第8期——Context.sol

news2024/11/18 21:42:11

Michael.W基于Foundry精读Openzeppelin第8期——Context.sol

      • 0. 版本
        • 0.1 Context.sol
      • 1. 目标合约
      • 2. 代码精读
        • 2.1 _msgSender()
        • 2.2 _msgSender()

0. 版本

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

0.1 Context.sol

Github: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.3/contracts/utils/Context.sol

Context库是合约开发中最常见的库,同时也是最让人迷惑的库。合约代码里面只将msg.sender和msg.data封装成了函数,感觉多此一举。实际上,本库不提供任何context环境切换的细节功能,而是需要目标合约中重写这两个函数起到了可编辑msg.sender和msg.data的目的。

最经典的应用就是ERC2771。

1. 目标合约

封装Context library成为一个可调用合约并且编写一个最小单元的可编辑msg context的demo:

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

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

import "openzeppelin-contracts/contracts/utils/Context.sol";

contract MockContext is Context {
	// worker发来的交易需要经过改变context处理
    address _worker;
    constructor(){
        _worker = msg.sender;
    }

    event MsgContext(address msgSender, bytes msgData, uint input);

    function _msgSender() internal view override returns (address){
        if (msg.sender == _worker) {
            address sender;
            assembly{
            	// 取calldata的后20个字节作为改变context后的msg.sender
                sender := shr(96, calldataload(sub(calldatasize(), 20)))
            }

            return sender;
        } else {
        	// 如果不是worker,直接返回父类的_msgSender()
            return super._msgSender();
        }
    }

    function _msgData() internal view override returns (bytes calldata){
        if (msg.sender == _worker) {
        	// 取calldata的后20个字节之前的全部字节作为改变context后的msg.data
            return msg.data[: msg.data.length - 20];
        } else {
        	// 如果不是worker,直接返回父类的_msgData()
            return super._msgData();
        }
    }

    function targetFunction(uint number) external {
        // emit the msg context in the function
        emit MsgContext(_msgSender(), _msgData(), number);
    }
}

全部foundry测试合约:

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

2. 代码精读

2.1 _msgSender()

直接返回msg.sender。

function _msgSender() internal view virtual returns (address) {
        return msg.sender;
}

2.2 _msgSender()

直接返回msg.data。

function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
}

foundry代码验证

contract ContextTest is Test {
    MockContext mc;

    event MsgContext(address msgSender, bytes msgData, uint number);
		
		// 以worker的身份去call MockContext的targetFunction方法
    function workerCall(address user, bytes memory inputBytes) external {
        // build metadata into calldata
        bytes memory callData = abi.encodePacked(inputBytes, user);
		// 以worker身份去call MockContext的targetFunction方法
        (bool ok,) = address(mc).call(callData);
        require(ok, "failed");
    }

    function test_MsgSenderAndMsgData() external {
        mc = new MockContext();
        bytes memory callData = abi.encodeCall(mc.targetFunction, (2048));

        // worker operation
        vm.expectEmit(address(mc));
        emit MsgContext(
            address(1024),
            callData,
            2048
        );
        this.workerCall(address(1024), callData);

        // common user operation
        vm.expectEmit(address(mc));
        emit MsgContext(
            address(1024),
            callData,
            2048
        );
        vm.prank(address(1024));
        mc.targetFunction(2048);
    }
}

可见,用户address(1024)自己发交易和worker组装calldata去调用MockContext合约的targetFunction方法,在其方法内部环境context是一样的,即:_msgSender()_msgData()和传参number都是一样的。

这样就实现了利用Context库对上下文的环境的编辑功能。

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

在这里插入图片描述
公众号名称:后现代泼痞浪漫主义奠基人

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

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

相关文章

MIT 6.S081 Lab 11 -- NetWork - 下

MIT 6.S081 Lab 11 -- NetWork -- 下 引言代码解析网络子系统初始化相关数据结构lab 分析e1000_transmit函数实现e1000_recv函数实现socket write全流程分析socket read全流程分析socket关闭ARP数据报的发送与接收 引言 本文为 MIT 6.S081 2020 操作系统 实验十一解析。 MIT …

HCIA-datacom认证最新资料共享

hcia认证有哪些值得推荐的学习方向? 入门首选学习方向:HCIA:Datacom!但是HCIA云计算(Cloud Computing)方向、HCIA 无线(WLAN)方向、HCIA Data Center Facility方向、HCIA 安全(Secur…

TTX1995可调谐激光器控制软件系统

画了两周时间,利用下班时间,设计了一个ITLA可调谐激光器控制软件,从硬件到软件。 这是使用的界面,实现了下面的功能: 1、模块信息的读取,包括生产日期,生产厂家,型号,序…

产品流程图

流程图设计 1.什么是流程图2.流程图元素定义3.几种常见的产品流程图 3.1业务流程图 | 泳道图(给产品经理看)3.2任务流程图(给程序员看)3.3页面流程图(给UI设计人员看) 4.如何绘制流程图 4.1调查研究4.2梳理…

笔试题之地区经济数据分析

数据分析通常应用于商业领域,但对于政府、非盈利组织等机构而言,在考量城市发展、监控环境质量等方面,也会涉及到数据分析。这时,就需要我们根据实际场景,结合数据分析的理论知识,发现其中的规律&#xff0…

Tensorflow入门(2)——深度学习框架Tesnsflow 线程+队列+IO操作 文件读取案例

目录 一、二、Tesnsflow入门 & 环境配置 & 认识Tensorflow三、线程与队列与IO操作1.队列实例:完成一个出队列、1、入队列操作(同步操作) 2.队列管理器 创建线程3.线程协调器 管理线程案例:通过队列管理器来实现变量加1,入队&#xff…

强化学习:实现了基于蒙特卡洛树和策略价值网络的深度强化学习五子棋(含码源)

【强化学习原理项目专栏】必看系列:单智能体、多智能体算法原理项目实战、相关技巧(调参、画图等、趣味项目实现、学术应用项目实现 专栏详细介绍:【强化学习原理项目专栏】必看系列:单智能体、多智能体算法原理项目实战、相关技巧…

好用的门店信息管理系统推荐?门店信息系统系统应该注重什么?

传统门店的信息管理模式总是会存在人工成本高,效率低,流程麻烦、数据复盘繁琐等问题。围绕门店信息管理过程中面临的各类痛点,蚓链数字化门店信息管理系统可以帮助门店更好的管理门店经营,货品盘点,库存管理&#xff0…

「XKOI」Round 3 赛后题解

比赛链接:「XKOI」Round 3 本题解同步发表于 洛谷:传送门 CSDN:传送门 文章目录 比赛链接:[「XKOI」Round 3](https://www.luogu.com.cn/contest/117863)A [T343985 CRH的工作](https://www.luogu.com.cn/problem/T343985)1.1 …

CRC算法并行运算Verilog实现

因为CRC循环冗余校验码的算法和硬件电路结构比较简单,所以CRC是一种在工程中常用的数据校验方法。尽管CRC简单,但在工程应用中还是有些问题会对工程师产生困惑。这篇文章将介绍一下CRC,希望对大家有所帮助。 一、CRC算法介绍 CRC校验原理看起…

PPO(Proximal Policy Optimization Algorithms)论文解读及实现

论文标题:Proximal Policy Optimization Algorithms 核心思路:使用off policy 代替on policy,用一个策略网络来产生数据,用一个策略网络来更新参数,分别为policy_old和policy 0 摘要 Whereas standard policy gradient methods …

Python自动化办公:pptx篇

文章目录 简介能做什么PPT要素介绍官方demo高阶引申参考文献 202201笔记迁移 简介 python-pptx包是用来自动化处理ppt的。 使用的第一步是安装 pip install python-pptx相比python-docx,python-pptx的使用更为麻烦一些,原因有很多,比如说&…

波奇学Linux:make和Makefile

make和Makefile自动化构建并能决定源文件调用顺序,同时不必再写gcc命令 第一行依赖关系,第二行是tab键开头,是依赖方法 依赖关系:目标文件:依赖文件。 依赖方法:目标文件和依赖文件间的关系。 如果只有一条…

es下载历史的tar文件

第一步进入官网找到历史版本 第二步复制历史版本名称组合成下面的链接 直接get访问下载。如下链接所示只需要修改7.3.0这个版本号 https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.3.0-linux-x86_64.tar.gz

ChatGLM使用记录

ChatGLM ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型,基于 General Language Model (GLM) 架构,具有 62 亿参数。结合模型量化技术,用户可以在消费级的显卡上进行本地部署(INT4 量化级别下最低只需 6GB 显存&#xff0…

opencv实战--角度测量和二维码条形码识别

文章目录 前言一、鼠标点击的角度测量二、二维码条形码识别 前言 一、鼠标点击的角度测量 首先导入一个带有角度的照片 然后下面的代码注册了一个鼠标按下的回调函数, 还有一个点的数列,鼠标事件为按下的时候就记录点,并画出点,…

uniapp微信小程序上传体积压缩包过大分包操作和上传时遇到代码质量未通过问题

1:首先我们得从项目最初阶段就得考虑项目是否要进行分包操作,如果得分包,我们应该创建一个与pages同级的文件夹,命名可以随意 2:第二部我们将需要分包的文件和页面放到分包文件夹里面subpage,这里我们得注意&#xff…

Python基础语法第三章之顺序循环条件

目录 一、顺序语句 二、条件语句 2.1什么是条件语句 2.2语法格式 2.2.1 if 2.2.2if - else 2.2.3if - elif - else 2.3缩进和代码块 2.4闰年的判断练习 2.5空语句 pass 三、循环语句 3.1while 循环 3.1.1代码示例练习 3.2 for 循环 ​3.3 continue 3.4 break 一…

给LLM装上知识:从LLM+LangChain的本地知识库问答到LLM与知识图谱的结合

前言 过去半年,随着ChatGPT的火爆,直接带火了整个LLM这个方向,然LLM毕竟更多是基于过去的经验数据预训练而来,没法获取最新的知识,以及各企业私有的知识 为了获取最新的知识,ChatGPT plus版集成了bing搜…

linux常用工具介绍

文章目录 前言目录文件查看ls1、查看详细信息(文件大小用K、M等显示)2、按照文件创建时间排序(常在查看日志时使用) sort1、排序数字 df 、du1、查看目录的大小2、查看目录 从大到小排序 显示前n个3、查看磁盘使用情况 tailf一些目…