
阅读时长 3 分钟
假 ERC-20 充值攻击:伪造事件日志如何欺骗加密索引器
2026 年 7 月 24 日,以太坊上一个合约发出一条日志,声称 0.29 ETH 已到达某地址。实际上没有任何 0.29 ETH 到账。交易执行成功,区块确认完毕,而链上的记录如今显示:发生过一笔转账。
这个落差——链上记录的内容与链上实际发生的事情之间的落差——就是整场攻击的全部。它不是对交易所的黑客入侵,而是一张伪造的收据,被提交给一个天生信任收据的系统。
这类攻击由来已久。研究人员假充值漏洞的记录可追溯到 2021 年的一篇 IEEE 论文,CoinDesk 曾报道 2020 年约有 10 亿美元的代币暴露于该风险。值得你花时间的不是它是否存在,而是 2026 年的版本成本何其低廉,以及在监控面板上看起来何其普通。
这笔交易实际包含什么
一个外部账户(EOA)调用某个合约。该合约产生两笔内部交易并写入一条事件日志。攻击者承担的全部风险敞口:gas 费。
事件日志就是攻击载荷。,内容如下:
Transfer (index_topic_1 address to, uint256 amount)
to: 0xC5518694Ef1A64eF0362eB5165A8A41e83Ff4C41
amount: 290000000000000000
读签名,不要读名字。
标准的 ERC-20 转账事件是 Transfer(address,address,uint256)——发送方、接收方、金额,前两个参数为索引参数,日志共三个 topic。
而这个事件只有一个索引参数、两个 topic。没有 from。这就是全部把戏。
真实的转账会记录发送方,而这条日志只记录了接收方,因为根本没有资产被转移。合约声明了自己的事件,把它命名为 Transfer,并赋予它一个任何代币标准都不会产生的形态。它的 topic 哈希——0x69ca02dd4edd7bf0a4abb9ed3b7af3f14778db5d61921c...——并不是 ERC-20 的签名哈希。这是一个顶着同样名字的另一个事件。
内部交易则提供了“佐证”。两笔内部交易都被标注为 Transfer,都携带 0.29 ETH,都源自该合约。一笔指向伪造日志中点名的地址,另一笔指回发起整场攻击的账户。其中一笔通过 callcode 执行——这是一种早已弃用的操作码,会在调用者自身的上下文中运行借用的代码,在现代正规合约中几乎绝迹。
肉眼查看调用追踪,看到的是一个收到调用并转移了 ETH 的合约;程序去解析它,看到的却是一笔充值。
交易所为什么会入账
充值入账本质上是一个索引问题,而索引器是模式匹配器。充值管道监视链上数据,判断哪些事件代表价值到达了自己控制的地址,然后记入余额。判断依据通常是以下条件的某种组合:是否存在名为 Transfer 的事件、to 字段是否匹配充值地址、金额是否可解析、交易是否成功。
上述条件在这里全部成立。交易成功了。事件名叫 Transfer。接收方匹配。金额干净地解析为 0.29 ETH。
失守的是一项许多管道从未做过的检查:事件 topic 哈希是否与 ERC-20 标准签名一致,以及由此产生的余额变化是否真实存在于链上状态中?
按事件名称匹配,你可以被喂进任何东西;按签名哈希匹配并与余额核对,这笔交易就完全无害。
随后是下半场。余额一旦入账,攻击者立即提现,兑付的是一笔毫无资产支撑的信用。交易所付出真实资产。假充值永远不会被对账发现,因为多数对账是几小时后的批量处理,而那时提现早已结算完成。
速度不是偶然,它就是这场攻击的核心。
2026 年版本为何值得警惕
三点原因,单独看都不新鲜。
- 成本只是一笔 gas。 不占用任何本金,尝试失败也无任何损失。这意味着攻击者可以把它撒向一百家平台,只需要其中一家的索引器足够宽松。
- 金额很小。 0.29 ETH 不会触发大额转账警报。首次尝试的目的不是获利——而是试探你的管道会不会入账。后续攻击的规模则按你的提现限额量身定制。
- 链上完全可读。 每个要素都是公开且经确认的。没有漏洞利用、没有私钥失窃、没有端点被攻破。你的日志会显示平静如常的一天。
最后一点在运营层面最为关键。不留痕迹的攻击难以检测;而这场攻击留下了完美的痕迹却依然难以检测,因为痕迹看起来毫无破绽。
三项检查
- 匹配签名哈希,而非事件名称。 你的索引器应将 topic0 与标准的 ERC-20 Transfer 哈希比对,其余无论标注成什么都应丢弃。仅此一项改动就能阻断本文描述的攻击。
- 对照状态验证,而非对照事件。 事件只是一项声明。入账前应查询余额并确认其确实发生了变化。事件只是为索引提供便利,从来就不是为结算证明而设计的;把事件当作证明,才是根本性错误。
- 在入账与提现之间留出时间。 无论你的确认策略如何,一笔消耗数秒前刚入账充值的首次提现,理应走与常规提现不同的通道。这场攻击依赖于两件事紧邻发生;把它们分开,你的成本微乎其微,攻击者的整个骗局则彻底报废。
对于在生产环境中运行这些控制而非从零设计的运营者:提现授权是一个策略层,而不是一个功能。它应该放在审批流、阈值与升级机制所在的同一层——那里也是“谁批准了什么”这一不可伪造记录的写入之处。
要点
7 月 24 日没有人闯入任何系统。一个合约写下了一句关于自己的话,而这句话专门设计给快速阅读的软件去误读。你的充值管道不是账本读取器,而是一个文档解析器——它一直在悄悄地相信文档对自己内容的描述是诚实的。


