ERC-4524 安全转账的 ERC-20:合约收币前要先举手确认 图 1
ERC-4524 安全转账的 ERC-20:合约收币前要先举手确认 · 图 1

ERC-4524 安全转账的 ERC-20:合约收币前要先举手确认

往一个错误地址转 ERC-20 代币,标准转账不会拦你;往一个根本不认识这种代币的合约转,钱同样石沉大海。NFT 玩家熟悉的那套 safeTransferFrom——转给合约先问一句”你收得了吗”——在 ERC-20 世界里长期缺席。ERC-4524 要补的就是这一问:转给合约时先调用收方的 onERC20Received,对方举手确认(返回指定选择器)交易才算数,否则整体回滚。按照以太坊 ercs 仓库的记录,这份提案状态为 Stagnant(停滞),创建于 2021 年 12 月 5 日。

一个选择器撑起整个安全语义

标准的规则写得很紧凑:实现该标准的代币在把代币转给外部合约时,必须调用目标合约的 onERC20Received,目标合约若实现了 ERC20Receiver 接口并返回函数选择器 0x4fc35859,转账继续;目标没实现这个接口,或者返回的不是这个值,转账必须 revert。转给普通外部账户(EOA)则按常规转账处理,无须回调。这套设计与 ERC-721 的 onERC721Received 完全同构,选择器值不同而已。对用户端的直观感受是:以前”手滑转进黑洞合约”是一去不回的事故,在这类代币上会变成一次失败的交易——Gas 照付,但币还在原处。

ERC-4524 安全转账的 ERC-20:合约收币前要先举手确认 图 2
ERC-4524 安全转账的 ERC-20:合约收币前要先举手确认 · 图 2

为什么顺手带上了 EIP-165

提案摘要里花了不少篇幅讲 EIP-165 的意义,这是 ERC-4524 容易被忽略的第二个贡献。作者举的例子是 permit 类扩展:一个平台对接各路 ERC-20 时,很难事前知道某只代币是否实现了 ERC-2612 的免授权签名,因为 ERC-2612 并不强制声明接口。ERC-4524 的观点是:NFT 系标准(ERC-721、ERC-1155)普遍内建 EIP-165 的 supportsInterface,这是它们扩展生态繁荣的原因之一;ERC-20 生态也应如此。因此这份标准同时要求代币合约通过 EIP-165 声明支持,其接口的 interfaceId 为 0x534f5876。工具端查一只代币”到底实现了什么”,多了一个可以盲试的标准问题。

回调是双刃剑:标准自己写明的重入风险

标准的安全考量一节毫不回避地指出:onERC20Received 是回调函数,历史上回调正是重入攻击的经典入口,实现时必须防止收币合约在回调里反手调用代币合约或其他外部合约。提案同时在接口里强制搭配 EIP-165 的 supportsInterface 声明,让钱包能事前探测对方是否真的实现了接收逻辑,而不是撞墙后才发现。这也解释了这类”安全转账”的悖论——为了避免”转错”这种事故,引入了”回调被利用”这种新风险面。对代币合约开发者,防线是先完成账本变更再触发外部调用、必要时加重入锁;对普通用户,需要理解的是安全转账只防”对方没能力收”,不防”对方有能力收但不该收”,钓鱼合约往往恰恰实现了完整回调来伪装合格收件人。

转账失败的排查顺序

支持这套标准的钱包做转账前,会先探测目标合约是否实现 ERC20Receiver:地址有代码而无回调,直接提示”可能收不了币”;地址无代码则按 EOA 正常放行。这套预检也给了用户一个实用的排错工具——转账 revert 时,先看失败原因里是否指向回调返回值不符:是,说明对方合约实现了收币接口但在回调里主动拒绝了这次转入,需要回到对方合约的事件与文档找原因;对方压根没有回调,则问题在代币端或目标地址本身。无论哪种,币都在原处,这比”成功但去向成谜”的传统失败模式友好得多。

值不值得期待

按 ercs 仓库口径,ERC-4524 停留在 Stagnant,即作者或社区已停止推进,主流 ERC-20 实现基本没有采纳;ERC-223 等替代路线各有存量,两条思路在”给 ERC-20 转账加回调”这个目标上殊途同归但互不兼容。实际意义在于读懂两类现象:某些小众代币确实实现了这套接口,转账失败回滚属正常防御;反之对绝大多数主流代币,防转错仍然只能靠地址簿、白名单和小额测试这些流程手段,而不是期待代币合约自带”举手确认”。本文为机制说明,不构成任何投资建议。