下面要介绍的ERC1820是以太坊区块链世界中的"中心化注册表",任何人可以通过它查询哪些合约或EOA地址是否支持哪些接口,以更加确定性的方式去交互。
当然你也可以为一个地址注册接口,使别人也可以随时查询到你的合约或EOA地址是否支持指定的接口。
之前学习了下ERC165标准,理解ERC165标准,发现ERC标准是一环扣一环,怪是越打越多的。希望以本文记录一下ERC1820的一些细节和主要实现,不会具体分析合约方法。
下面要介绍的ERC1820是以太坊区块链世界中的"中心化注册表",任何人可以通过它查询哪些合约或EOA地址是否支持哪些接口,以更加确定性的方式去交互。
当然你也可以为一个地址注册接口,使别人也可以随时查询到你的合约或EOA地址是否支持指定的接口。
. ERC1820标准的功能主要为查询、和注册。
查询 查询一个指定的地址(可以是EOA,也可以是合约),是否实现了指定的接口(这里兼容ERC165接口)。
. 注册 注册可以达到三个效果,你可以选择如何注册。
.
通过不同的身份理解ERC1820
ERC1820有三个身份,分别是 目标地址(target)、管理者(manager)、实现者(implementer),这三个身份分别有不同的作用。
目标地址(target)
1.默认要为哪个地址查询(或实现)接口 2.查询接口也是通过这个地址 + 要查的接口Hash 来进行查询
管理者(manager)
1.只有manager才能改变一个地址的接口
- 一个目标地址的默认manager是这个目标地址本身 3.manager可以设置修改一个新的manager
实现者(implementer)
1.默认是目标地址自身 2.当为EOA地址注册接口,或希望为合约代理实现接口,此时implementer就是那个代理实现合约。 3.在通过erc1820查询接口是否注册时,返回的就是implementer地址。
了解了这三个身份,就可以很好的理解ERC1820的设计。
下面列出ERC1820的主要方法,并了解如何使用。
//【作用:查询一个目标地址是否实现了某个接口】
//1.未注册返回0地址,注册则返回 实现者(implementer)地址
//2.接口Hash(_interfaceHash)的计算方法
//keccak256(abi.encodePacked(_interfaceName));
//3.这里参数_interfaceName 就是接口的字符串,比如"IERC20Token"
//4._interfaceHash也可以兼容传入erc165接口ID,但需要填充满bytes32(erc165接口ID是bytes4)
function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address);
// 【作用:设置接口实现者】
//1._addr必须是msg.sender,所以这就意味着EOA地址的接口注册也需要这个EOA来完成。
//2.若是为自己实现接口,默认_addr和_implementer是同一个地址
//3.ERC1820中只能兼容查ERC165接口,但不能为ERC165注册。 所以_interfaceHash只能是ERC1820接口。
//4.为了方便多签,若把_addr传入0地址,则默认会把_addr设为msg.sender。这样多签可以复用同样的交易数据。
function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external;
// 【作用:设置地址的管理者】
//_addr必须为原manager,默认是目标地址
function setManager(address _addr, address _newManager) external;
// 【作用:获取地址的管理者】
function getManager(address _addr) external view returns(address);
//【 作用:计算接口哈希值】
//此方法是ERC1820标准为了方便人们算接口Hash提供的,其实也只是keccak256 + encodePacked 接口名称。
function interfaceHash(string calldata _interfaceName) external pure returns(bytes32);
// 【作用:更新 ERC165 缓存】
//此方法必须手动调用更新缓存,ERC1820不会主动更新缓存。
//如果你想通过ERC1820储存你项目的ERC165接口,那么当你每次接口改变,最好同时也调用此方法更新缓存记录。
function updateERC165Cache(address _contract, bytes4 _interfaceId) external;
// 检查合约是否实现了 ERC165 接口
function implementsERC165Interface(address _contract, bytes4 _interfaceId) external view returns (bool);
// 当没有ERC165缓存时,以staticall方式去目标合约查。
function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) external view returns (bool);
.
. 【ERC165和1820查询实现不同细节对比】 ERC1820的实现中有很多值得学习和需要细心发现的细节。
对于ERC1820的部署,其实需要先简单理解一下交易签名。
2.ERC1820官方提案中就是提供了这样一个用于部署的交易字符串
为了实现任何人可以在任何链上,都能够部署得到同样的ERC1820合约地址,达到统一的效果,采用了一种无需私钥的部署方式。
知识点:
如下:ERC1820的签名r、v、s数据
v: 27,
r: 0x1820182018201820182018201820182018201820182018201820182018201820'
s: 0x1820182018201820182018201820182018201820182018201820182018201820'
这里有一些细节
上面是分析了一下部署原理,下面说一下步骤。 由于部署后的from是0xa990077c3205cbDf861e17Fa532eeB069cE9fF96
理想来说,作为开发者或项目方,你可以为一个指定的用户(EOA)地址,实现一些特定的逻辑。
比如当用户收到代币、就代他进行投票、或存款之类的操作。 如ERC777就默认实现了转账接收钩子(tokensReceived)。
但这个为EOA地址实现接口功能,2点原因导致使用受限;
另外还有一个不算友好的地方,ERC1820中只能由msg.sender来为自己注册接口,所以这个EOA用户也只能自己去调用方法,对用户的要求比较"高"。
最近抽空学习ERC1820的官方提案,断断续续用了大概一周多的时间。
ERC1820的合约实现的也有很多很巧妙的地方,很值得去学习。这过程中涉及到一些相关的内容、比如以太坊的签名与交易、无秘钥部署、EIP155、ERC165等..
感觉想把ERC1820通过一篇文章写的非常清晰,是挺不容易的,只能算一些笔,还是感觉有不少收获的。
另外看到以太坊主网的ERC1820合约部署五年多,也没几个人调用注册,真是可惜了这么好的合约。
参考来源 EIP1820官方提案:https://eips.ethereum.org/EIPS/eip-1820 ERC1820优质文章:https://www.decipherclub.com/erc-1820/
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!