·
以太坊临时拉闸:Gas 一改,13 个老合约的失败变成永久
Hoodi 测试网的 Glamsterdam 升级临时取消,200M gas limit 也一起撤了。原因不是代码没写完,而是 EIP-8037 改了失败后还剩多少 gas,13 个已在主网的合约可能把可重试的失败变成永久记账。
10 月 22 日,以太坊基金会发了条很短的公告:Hoodi 测试网上的 Glamsterdam 升级取消,新的激活日期待定。同一份公告里还顺手撤掉了 Hoodi 原本要涨到 2 亿的 gas limit。
之前定的时间是 10 月 26 日 17:42:48 UTC,epoch 132,352,连秒都算好了。核心开发者在 ACDE #248 上决定不做了。理由不是代码没写完,而是已经部署在主网上的合约可能被改坏。
问题出在 EIP-8037。
简单说,它把「执行」和「创建状态」拆成两个池子。今天写一个新的 storage slot 花 22,100 gas,从同一个池子里扣;Glamsterdam 之后变成 12,100 执行 gas,再加 97,920 的 state gas,从另一个 reservoir 里扣。这个 reservoir 不遵守 63/64 的转发限制,整包传给子调用,而 GAS 指令——也就是 Solidity 里的 gasleft()——只报执行 gas。
这就掀了一张很老的桌子。
很多合约里都有这种写法:
(bool ok, ) = target.call(data);
if (!ok) failed[id] = true;
它有一个隐式自保:如果攻击者故意只给一点点 gas 让目标调用 OOG,那剩下的 gas 也不够把 failed[id] 写进 storage,整个交易 revert,操作还能重试。这就是防 insufficient gas griefing 的那道墙。
EIP-8037 之后,执行 gas 变便宜了,reservoir 还可能把 gas 还回来,写「失败记录」的 gas 就够了。于是本来会被整体回滚的操作,变成失败被永久记账。本来能重试的支付、批量结算、跨链消息,一次性被判死刑。
ChainSecurity 在 10 月 13 日发了技术分析,随后找出 13 个已经在主网上跑的合约中招。项目名没公开,目前还在私下沟通。开发团队进 ACDE #248 时,议程上写的是敲定 12 月 1 日、8 日还是 9 日上主网;出来的时候,三个日期全都悬着。
我的看法:这件事的重点不是「以太坊又跳票」,而是 gas 一直是被当成隐式 API 用的。十年里大家把 gasleft() 当安全边界,却从没有人在规范层面保证过它。现在协议层动计价,等于一次性给所有存量合约做体检,而体检是在 Last Call 阶段才开始的。
对照一下隔壁:10 月 21 日,Solana 的 Alpenglow 准点上主网,最终确认从 12.8 秒压到 150 毫秒。以太坊这边,预测市场上「2027 年前上线」的赔率只剩 54%。
我不觉得这就能证明 Solana 更强。Solana 改的是共识,节点升完级就生效;以太坊改的是计价,改完所有老合约都得重新对表。慢有慢的道理。但这次慢的位置挺尴尬:不是慢在写代码,是慢在给十年前的合约补课。
写合约的可以现在做三件事:翻一遍 hardcode 的 gas stipend 和 gasleft() 检查;重新跑 gas 估算,别用缓存的数;重点看那些「把失败写进永久状态」的分支。
免责声明:以上内容仅供娱乐交流,不构成任何投资建议。DYOR。
转发此帖子?
与您的关注者分享。
回复