ERC-165 接口探测:合约自报家门的方式与两个坑
市场在挂出一个 NFT 合约前,常要确认它到底实现了哪些标准;对 ERC-721、ERC-1155 各类扩展的识别,大多靠一个函数完成:supportsInterface。这就是 ERC-165。本文讲它的原理、正确用法和两个容易被误解的边界。
接口怎么被命名:选择器异或
ERC-165 把“接口”定义为一组函数选择器的集合,接口标识是这些选择器做异或运算得到的 4 字节值。比如查询函数 supportsInterface(bytes4) 自身,其标识就是 bytes4(keccak256("supportsInterface(bytes4)")),结果为 0x01ffc9a7。合约实现这个函数后,按约定对各类输入返回:被查 0x01ffc9a7 时返回 true,表明自己支持 ERC-165 本身;被查 0xffffffff 时必须返回 false;对自己实现的其他接口标识返回 true,其余返回 false。函数还要求是 view 且消耗不超过 3 万 gas,保证探测便宜且无副作用。
两步确认:先验身份,再查目标
要确认某个合约真的实现了某个接口,文档给出两步法。第一步先探测该合约是否支持 ERC-165:传入 0x01ffc9a7 应返回 true,同时传入 0xffffffff 应返回 false,两项都符合才认为对方诚实实现了探测函数。第二步再传入目标接口的标识拿结论。如果第一步就不合格,你无从判断第二步的 true 是不是随口应答。
坑一:谎报接口
supportsInterface 是合约代码写的,恶意合约可以对自己根本没实现的接口返回 true。探测能筛掉明显不合规的合约,却挡不住一个声称兼容 ERC-721、实际 transferFrom 行为扭曲的合约。防御方式是在探测之外叠加行为测试:对测试网或小额资产实际走一遍转账与授权,观察事件与返回是否符合规范,而不是只读一个布尔值。
坑二:查不出事件型扩展
接口标识由函数选择器组成,因此纯事件类扩展没有可查询的函数标识。ERC-2309 就是典型:它只增加一个 ConsecutiveTransfer 事件,不提供新函数,用 ERC-165 查不出“支持 ERC-2309”这个结论。ERC-5615 也在文档里明确该扩展不强制走 ERC-165 发现机制。判断这类扩展是否生效,只能读合约源码、查事件日志或直接调用相关函数。
实用查询清单
对普通持有人,有价值的顺序是:先确认合约实现了你要交互的标准(比如 ERC-721 的接口标识),再做 ERC-165 身份两步验证,最后对关键扩展(版税声明、批量事件等)用函数调用或事件日志单独确认。三层都过,才谈得上这个合约在技术层面看起来规范。
常见接口标识速查
实操里高频出现的标识有几个:ERC-165 本身是 0x01ffc9a7;ERC-721 的核心接口、ERC-721Metadata、ERC-1155 等各有固定值,都能在标准文档或主流合约库源码里查到,注意以文档标注的 XOR 计算结果为准,不要采信论坛帖子里的转抄值。查询入口通常是区块浏览器的合约页或读函数面板,填标识、点查询,一次交互就能完成。把标识记错是新手最常见的乌龙,比对来源时优先选 eips.ethereum.org 原文。
最后补一个视角:ERC-165 诞生于去中心化交易所需要安全判断代币类型的场景,它的价值在于把口头承诺变成可编程查询。但也正因为查询成本极低,接口标识本身成了一种可以伪装的名牌。成熟的核验永远是把便宜的查询当作筛选器,把昂贵的实际交互当作验证器,两者缺一不可。
补充一个成本事实:标准限定探测函数消耗低于三万 gas,所以批量扫描一批合约的接口支持情况在只读节点上几乎免费,查询不改变链上状态,可以放心反复尝试,这也解释了为什么它比逐行读源码更适合普通持有者做第一轮筛选。
风险提示:本文仅介绍合约接口标准,不构成任何投资建议。接口探测通过不代表合约安全或资产有价值。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。