同一条合约调用,重复执行时 Gas 有时差别很大,问题往往出在状态访问的冷与热。EIP-2929 给以太坊的所有状态读取定价定了两条轨道:这笔交易里第一次碰的数据按冷价收,碰过的再碰按暖价收。这篇文章拆解它的规则、来由,以及对用户 Gas 估算的实际影响。
为什么要给“第一次访问”单独定价
在 EIP-2929 之前,读一个存储槽、查一个账户余额或代码,Gas 价都定得很低。低到什么程度——2016 年上海的拒绝服务攻击中,攻击者最持久有效的手段之一就是发送访问海量不同账户的交易;EIP-2929 文本引用研究显示,当时这类恶意交易在节点上重放一次要二十到八十秒,普通交易只要几毫秒。状态访问逼着节点去磁盘里翻梅克尔树,代价被严重低估。EIP-2929 把 SLOAD 首次读取提到 2100 Gas,把 CALL、BALANCE、EXT* 这类账户访问提到 2600 Gas,约三倍的涨幅,同一笔交易内重复访问同一目标的则降到 100 Gas。文本规定从第 12244000 个区块起生效,对应 2021 年的柏林升级,状态为 Final。
冷热怎么判定:每笔交易两张清单
节点执行每笔交易时维护两个集合:已访问地址集和已访问存储键集。交易开始时,发送方、接收方和全部预编译合约地址预先放入地址集,存储键集为空。此后每次状态访问先查清单:不在清单里就算冷访问,收冷价并写入清单;已在清单里就算暖访问,只收 100。集合的作用域是整笔交易,内层调用若回滚,清单回退到进入该作用域前的状态。

EIP-2930 引入的访问清单交易类型走得更远:发交易时就把打算访问的地址和存储键预先声明出来,每个地址收 2400 Gas、每个存储键收 1900 Gas;声明过的目标直接进入已访问清单,实际执行时的读取只剩 100 的暖价,清单之外再碰的照旧按冷价罚。对循环读取可预测存储键的合约,这种“先买票再进场”的交易往往比纯冷访问划算——EIP-2930 文本列出的首要动机正是给被高价状态访问卡住的合约松绑,并顺带为区块级见证等无状态方向预留了数据格式。
用户会看到什么
第一,同一函数里循环读十个从未碰过的槽,比循环读十个本交易已暖的槽贵得多,Gas 估算工具算出来的是这个混合结果。第二,跨交易的重复读取一律是冷的——上一笔交易访问过什么对本笔没有任何加成,清单不跨交易延续。第三,钱包估算值偏高或偏低时,一个重要来源是合约实际访问的冷热结构变化,而不是简单的“Gas 单价涨了”。EIP-2929 文本还提到一个副产品:给状态访问定高价顺带压低了无状态见证的体积上限,为以后轻节点验证铺路。
拿两个极端做个算术示意(只看读操作,不含 21000 的基础交易 Gas 与写入费用):一笔交易读五十个各不相同、此前没碰过的存储槽,光读就要五十乘两千一百等于十万五千 Gas;如果这五十个槽已经在同一笔交易里被访问过,或事先写进了访问清单,同样的读取只要五十乘一百等于五千 Gas,两者相差二十倍。换句话说,冷热结构在重逻辑交易里可以左右总账单的一半以上,这不是夸张,而是常数直接推出来的区间。
边界与风险提示
冷热规则只影响 Gas 计量,不改变交易成功与否;它也不保证估算精确,区块拥堵、Gas 上限变化都会叠加影响。对开发者,它提醒“省 Gas”要按访问模式而不是指令条数来优化;对用户,它是理解账单波动的一个关键变量。本文为协议机制的科普说明,不构成投资建议;Gas 相关数值以 EIP 文本与客户端当前实现为准。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。