Michael.W基于Foundry精读Openzeppelin第26期——ERC1820Implementer.sol

news2024/11/25 14:43:38

Michael.W基于Foundry精读Openzeppelin第26期——ERC1820Implementer.sol

      • 0. 版本
        • 0.1 ERC1820Implementer.sol
      • 1. 目标合约
      • 2. 代码精读
        • 2.1 _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal
        • 2.2 canImplementInterfaceForAddress(bytes32 interfaceHash, address account)
        • 2.3 foundry代码验证

0. 版本

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

0.1 ERC1820Implementer.sol

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

ERC1820Implementer合约是对IERC1820Implementer interface的实现。该合约往往是与ERC1820Registry合约配合使用。

如果想要合约成为ERC1820Registry记录在案的implementer,需要目标合约继承ERC1820Implementer并且调用_registerInterfaceForAddress()向外公布自己的implementer意愿。之后,ERC1820Registry中的对应account的管理员再调用ERC1820Registry.setInterfaceImplementer()进行注册确认。

1. 目标合约

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

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

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

import "openzeppelin-contracts/contracts/utils/introspection/ERC1820Implementer.sol";
import "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";

contract MockERC1820Implementer is ERC1820Implementer, ERC721("", "") {
    function registerInterfaceForAddress(bytes32 interfaceHash, address account) external {
        _registerInterfaceForAddress(interfaceHash, account);
    }
}

全部foundry测试合约:

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

2. 代码精读

2.1 _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal

设置本合约成为account名下的interfaceHash的implementer。

	// magic值(常量)
    bytes32 private constant _ERC1820_ACCEPT_MAGIC = keccak256("ERC1820_ACCEPT_MAGIC");
	// 用于记录本implementer合约在ERC1820 register中的映射关系的mapping
	// ERC1820 register中记录的映射关系:address名下,interface hash => implementer address
    // 由于一个implementer可以由多个address共享,所以:
    // - 第一个key为interface hash;
    // - 第二个key为所属名下的address;
    // - 第二个key对应的value表示本合约地址是否是address(第二个key)名下的interface hash(第一个key)的implementer
    mapping(bytes32 => mapping(address => bool)) private _supportedInterfaces;
    
    function _registerInterfaceForAddress(bytes32 interfaceHash, address account) internal virtual {
    	// interfaceHash作为第一个key,account作为第二个key,对应的value设置为true。这样,本合约在面对ERC1820 register的查询时可以二次确认自己与account和interfaceHash之间的关系
        _supportedInterfaces[interfaceHash][account] = true;
    }

2.2 canImplementInterfaceForAddress(bytes32 interfaceHash, address account)

对外提供的查询方法。如果本合约承认自己是account名下的interfaceHash的implementer,返回magic值。否则返回0值。

    function canImplementInterfaceForAddress(bytes32 interfaceHash, address account)
        public
        view
        virtual
        override
        returns (bytes32)
    {
    	// 如果mapping _supportedInterfaces中记录的第二个key的value为true,返回magic值,否则返回bytes32(0x00)
        return _supportedInterfaces[interfaceHash][account] ? _ERC1820_ACCEPT_MAGIC : bytes32(0x00);
    }

2.3 foundry代码验证

contract ERC1820ImplementerTest is Test {
    MockERC1820Implementer mei = new MockERC1820Implementer();
    ERC1820Registry er = new ERC1820Registry();
    bytes32 constant ERC1820_ACCEPT_MAGIC = keccak256("ERC1820_ACCEPT_MAGIC");

    function test_ERC1820Implementer() external {
        address account = address(1024);
        bytes32 interfaceHashERC721 = er.interfaceHash("ERC721Token");
        // no registered interface
        assertEq(0, mei.canImplementInterfaceForAddress(interfaceHashERC721, account));

        // revert when set implementer in ERC1820Registry before register operation in ERC1820 implementer
        vm.prank(account);
        er.setManager(account, address(this));
        vm.expectRevert("Does not implement the interface");
        er.setInterfaceImplementer(account, interfaceHashERC721, address(mei));

        // register interface between ERC1820Registry and ERC1820Implementer
        // 1. register willing in ERC1820Implementer
        mei.registerInterfaceForAddress(interfaceHashERC721, account);
        assertEq(ERC1820_ACCEPT_MAGIC, mei.canImplementInterfaceForAddress(interfaceHashERC721, account));
        // query for interface hash not registered
        bytes32 interfaceHashOther = er.interfaceHash("ERC20Token");
        assertNotEq(ERC1820_ACCEPT_MAGIC, mei.canImplementInterfaceForAddress(interfaceHashOther, account));
        // query for account not registered
        assertNotEq(ERC1820_ACCEPT_MAGIC, mei.canImplementInterfaceForAddress(interfaceHashERC721, address(1024 + 1)));

        // 2. set implementer in ERC1820Registry
        er.setInterfaceImplementer(account, interfaceHashERC721, address(mei));

        // 3. check from ERC1820Registry
        assertEq(address(mei), er.getInterfaceImplementer(account, interfaceHashERC721));
    }
}

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

在这里插入图片描述

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

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

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

相关文章

Java的反射机制、Lambda表达式和枚举

Java的反射机制、Lambda表达式和枚举 文章目录 Java的反射机制、Lambda表达式和枚举1.反射机制反射的概念、用途、优缺点反射相关的类及使用(重要!!)相关类Class类:代表类实体,表示类和接口Field类&#xf…

URLSearchParams:JavaScript中的URL查询参数处理工具

文章目录 导言:一、URLSearchParams的来历二、URLSearchParams的作用三、URLSearchParams的方法和属性四、使用示例五、注意事项六、结论参考资料 导言: 在Web开发中,处理URL查询参数是一项常见的任务。为了简化这一过程,JavaScr…

论文阅读——Adversarial Eigen Attack on Black-Box Models

Adversarial Eigen Attack on Black-Box Models 作者:Linjun Zhou, Linjun Zhou 攻击类别:黑盒(基于梯度信息),白盒模型的预训练模型可获得,但训练数据和微调预训练模型的数据不可得&#xff…

龙迅LT86102UXE产品概括,HDMI2.0转一分二HDMI2.0/1.4,支持音频剥离,支持4K60HZ

LT86102UXE 1. 一般说明 龙迅 LT86102UXE HDMI2.0 分路器具有符合 HDMI2.0/1.4 规范的 1:2 分路器、最大 6Gbps 高速数据速率、自适应均衡 RX 输入和预加重 TX 输出(用于支持长电缆应用)、内部 TX 通道交换以实现灵活的 PCB 布线。 LT86102…

A Survey for In-context Learning

A Survey for In-context Learning 摘要: 随着大语言模型(LLMs)能力的增长,上下文学习(ICL)已经成为一个NLP新的范式,因为LLMs仅基于几个训练样本让内容本身增强。现在已经成为一个新的趋势去探索ICL来评价和extrapolate LLMs的能力。在这篇…

vue3+element-plus表格默认排序default-sort失效问题

场景 在使用动态数据渲染的场景&#xff0c;el-table设置默认属性default-sort失效。 原因 el-table的default-sort属性是针对静态数据的&#xff0c;如果是动态数据&#xff0c;default-sort则无法监听到。 案例&#xff1a;静态数据 <template><el-table:data&…

一文分析多少杠杆最高

在进行加杠杆操作时&#xff0c;合约产品通常会有一定的杠杆比例限制&#xff0c;这是由监管机构或交易平台设定的。杠杆比例限制的目的是为了控制风险&#xff0c;避免过度杠杆化导致的潜在损失过大。 不同的交易平台和合约产品可以有不同的杠杆比例限制。一般来说&#xff0…

堆叠注入进阶--(buuctf-随便注、GYCTF-black_list)【多方法详解】

了解一下 堆叠注入基础知识及其他题目&#xff1a; SQL-堆叠注入 终于有时间来填填坑了 Buuctf-随便注 算是堆叠注入中非常经典的题目了。 随便试试就能看到黑名单&#xff1a; 没了select&#xff0c;其实大概率就是堆叠注入 先探测一下&#xff1a; 1;show databases;…

Struts2一次请求参数问题的记录

最近&#xff0c;一次前端正常请求&#xff0c;但后台出现请求参数值的变化&#xff0c;导致报错&#xff0c;问题如下&#xff1a; 从入参request中查看请求参数&#xff0c;是一个Json字符串&#xff0c;其中有个description的键值对&#xff1b; 但是&#xff0c;接下来调用…

分布式websocket解决方案

1、websocket问题由来 websocket基础请自行学习,本文章是解决在分布式环境下websocket通讯问题。 在单体环境下,所有web客户端都是连接到某一个微服务上,这样消息都是到达统一服务端,并且也是由一个服务端进行响应,所以不会出现问题。 但是在分布式环境下,我们很容易发现…

【Vue】Vue2创建移动端项目实战教程,创建移动端项目保姆级教程,设置axios,utils工具包,vue.fonfig.js配置项 (下)

系列文章目录 这里是创建移动端项目 【Vue】Vue2.x创建项目全程讲解&#xff0c;保姆级教程&#xff0c;手把手教&#xff0c;Vue2怎么创建项目&#xff08;上&#xff09; 【Vue】Vue2创建移动端项目实战教程&#xff0c;创建移动端项目保姆级教程&#xff0c;接上一篇创建Vue…

解压版 MySQL 数据库的安装与配置

目录 1 下载2 安装3 配置3.1 添加环境变量3.2 新建配置文件3.3 初始化MySQL3.4 注册MySQL服务3.5 启动MySQL服务3.6 修改默认账户密码 4 登录MySQL5 卸载MySQL 安装环境:Win10 64位 软件版本:MySQL 5.7.24 解压版 1 下载 点击链接 进入如下界面 ❗️注意&#xff1a; 我们一般不…

JavaEE初阶:多线程 - 编程

1.认识线程 我们在之前认识了什么是多进程&#xff0c;今天我们来了解线程。 一个线程就是一个 "执行流". 每个线程之间都可以按照顺讯执行自己的代码. 多个线程之间 "同时" 执行 着多份代码. 引入进程这个概念&#xff0c;主要是为了解决并发编程这样的…

JAVA集合-List

// 数组的缺点&#xff1a;每次使用都需要指定长度&#xff0c;掉率低&#xff0c;操作麻烦 // // 【java集合体系】&#xff1a;分类&#xff1a;6个接口&#xff0c;1个工具类 // 6个接口&#xff1a; 单列 :Collection,(父接口) // …

成功项目管理必备的五个关键因素

在任何组织中&#xff0c;良好的项目管理都是项目成功的首要标准。然而&#xff0c;一旦被淹没在无穷无尽的任务、持续的紧迫性和利益相关者相互冲突等情况中&#xff0c;管理好项目可能会让你感到力不从心。找出项目成功的关键因素并加以解决&#xff0c;就能避免一切失败。 …

浅谈学生宿舍安全用电管理存在的问题及防范措施

安科瑞 华楠 摘要&#xff1a;2009年&#xff0c;由一个小小的“热的快”引起的学院女生火灾事件&#xff0c;再一次敲响了大学生安全用电的警钟。而近年来随着教育事业的蓬勃发展和教育体制的推进&#xff0c;我国高等教育总规模在逐年增加。而目前高等学校能源使用主要是以电…

产品帮助中心的制作方法,保姆级0-1完整的实操教程!

帮助中心是一个产品的重要用户自助服务模块&#xff0c;包括各类产品相关信息&#xff0c;用以帮助用户快速理解和使用产品功能。对于我们产品开发和管理者而言&#xff0c;设计帮助中心的初衷是解决用户困惑&#xff0c;怎么设计帮助中心&#xff0c;才能让其价值尽可能的大&a…

【C语言】每日一题(寻找数组的中心下标)

寻找数组的中心下标&#xff0c;链接奉上 方法 暴力循环前缀和 暴力循环 ​​​​​​​思路&#xff1a; 依旧是我们的老朋友&#xff0c;暴力循环。 1.可以利用外层for循环&#xff0c;循环变量为数组下标&#xff0c;在循环内分别求出下标左边与右边的sum 2.在边界时讨论&…

伙伴云CEO戴志康:让数据和业务更好的互通展现,数字化与可视化同步进行

近日&#xff0c;零代码平台伙伴云产品「页面」功能正式上线&#xff0c;在【小伙开麦】直播间&#xff0c;CEO戴志康和产品经理共同为在线观众展示「页面」的功能与使用技巧&#xff0c;让小伙伴们大呼过瘾&#xff01;好玩、好用、好看的「页面」&#xff0c;到底有哪些亮点&…

动手学深度学习-pytorch版本(一):引言 预备知识

参考引用 动手学深度学习利用 Anaconda 安装 pytorch 和 paddle 深度学习环境 pycharm 安装 0. 环境安装 利用 Anaconda 安装 pytorch 和 paddle 深度学习环境 pycharm 安装 1. 引言 机器学习&#xff08;machine learning&#xff0c;ML&#xff09;是⼀类强⼤的可以从经…