ERC-820 接口登记处:普通地址也能对外声明“我支持某接口”
程序合约能自带 supportsInterface 函数自报功能,普通钱包地址却做不到——它背后没有代码。2018 年 1 月 5 日创建的 ERC-820 就是为了补这个缺口:它定义了一张全网通用的登记表,任何地址(合约或普通账户)都可以在表上写明“我支持某个接口,具体逻辑由某个合约负责”。按 ercs 仓库记录,这份标准状态为 Final。
接口键是名称的哈希
登记表的键不是接口编号,而是接口名称字符串的 keccak256 哈希,例如把 ERC777TokensRecipient 这串名字算成一个 bytes32 值。登记表提供 interfaceHash 函数帮你在链上算出这个键。查询用 getInterfaceImplementer(地址, 接口哈希):返回登记过的实现者合约地址,查不到就返回零地址。也就是说,“支持”在这套体系里的含义是“表上有一条指向实现合约的记录”,而不是“这个地址真的有一段代码”。

谁有权登记:manager 机制
每个地址默认是自己的管理者,调 setInterfaceImplementer 时要求调用者恰好是该地址的 manager。普通账户想让别人(比如多签或代理合约)替自己维护登记,先用 setManager 移交管理权;把 manager 设成地址自身等于取消移交。如果登记的实现者不是调用者本身,登记表还会先问那个实现合约一句 canImplementInterfaceForAddress,只有它返回约定的 ERC820 魔法值,登记才会写进去——这道确认防止有人把别人的合约冒名挂到自己名下。
与 ERC-165 的分流和缓存
标准规定:接口哈希的后二十八个字节全为零时,这条查询被视为 ERC-165 风格的接口探测,登记表不查自己的账,而是转去直接问目标合约的 supportsInterface,失败则返回假。为了省 Gas,登记表还兼做 ERC-165 结果的缓存,任何人都可以调 updateERC165Cache 刷新某条记录。这意味着缓存值可能滞后于合约的真实状态,较真的集成方应当用 implementsERC165InterfaceNoCache 再核对一次。
为什么后来的项目要用 ERC-1820
ERC-820 原文开头就用醒目提示说明它已被 ERC-1820 取代,并要求新实现必须改用后者。原因很具体:Solidity 0.5 更新让 ERC-820 内嵌的 ERC-165 判定逻辑出现了不兼容,ERC-1820 修掉这个缺陷,其余功能与 ERC-820 等价。两者部署在各自链上保持同一地址,这套“跨链同址”思路后来也被别的注册表标准沿用。
能说明什么,不能说明什么
地址、Gas 与两个容易踩空的细节
先看部署。为了让注册表合约地址以 0x820 开头,官方实现用了一种叫 vanity 的撞号手段——代码注释里保留了撞出来的随机数记录,这也是“跨链同址”的由来:标准允许它部署在任何链上,并在所有链共享同一个地址,集成方不必逐链查注册表位置。接口名示例用的是 ERC777TokensRecipient,把名字直接 keccak256 后作为登记键。
两个容易踩空的细节值得单列。第一,setInterfaceImplementer 明确拒绝后二十八字节为零的哈希,会直接 revert 并提示不能写 ERC-165 哈希——这类键只能走转发的实时查询,想通过登记“冒充”ERC-165 探测结果是不行的。第二,地址参数传零时按 msg.sender 处理。标准解释这是为了和多签场景配合:多签发起的交易数据在所有实例上可以保持常量,不必为每个实例改参数。最后看一眼 Gas 模型:登记表探测 ERC-165 用固定三万 Gas 上限的静态调用,超支或失败都判假,这个上限写死在汇编里——遇到重型 supportsInterface 实现的合约时,登记表可能把它误判为不支持,缓存里的假值要靠 updateERC165Cache 再刷。
登记表能说明的是:某个地址在某个时间点声明了接口归属,且事件日志可查。不能说明的是:实现合约的行为一定安全,登记一定及时更新,也不能说明普通账户“真的实现了”某功能——那只是一条可以被 manager 随时改写的记录。把它当作地址名片可以,当作安全保证不行。本文为机制说明,不构成任何投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。