动态访问列表:柏林硬分叉如何降低特定交易的Gas成本

核心概念解读 / 浏览:22

当Gas费成为“数字房产税”,柏林硬分叉带来了什么?

2021年4月15日,以太坊主网在区块高度12,244,000处完成了柏林硬分叉升级。这次升级在当时的聚光灯下远不如后来的伦敦硬分叉(EIP-1559)那般耀眼,但它埋下了一颗对Layer2、跨链桥、复杂DeFi交互至关重要的“技术彩蛋”——EIP-2930:可选访问列表(Optional Access Lists)

如果你曾经在Uniswap V3上为一个流动性池添加流动性,或者在Gnosis Safe上执行一笔多签交易,你大概率经历过Gas费高到离谱的“至暗时刻”。而柏林硬分叉引入的动态访问列表机制,正是针对这类“特定交易”的一剂精准解药。

本文不打算复述EIP的枯燥原文,而是用“城市交通”的比喻,带你拆解访问列表如何工作、为何能省钱、以及它如何与后来的EIP-1559、Proto-Danksharding形成技术接力。

一、先理解“冷地址”与“暖地址”:Gas的隐形税收

以太坊的EVM(以太坊虚拟机)在执行交易时,每接触一个存储槽(Storage Slot)地址(Address),都需要支付一笔Gas费用。但这里有个关键细节:如果同一个交易里,某个地址或存储槽被多次访问,第一次访问是“冷访问”,后续访问是“暖访问”

  • 冷地址访问(Cold Access):成本为 2,600 Gas
  • 暖地址访问(Warm Access):成本仅为 100 Gas

差距高达26倍。为什么EVM要这样设计?因为以太坊节点需要从磁盘或状态树中加载数据,第一次加载是“冷启动”,代价高;之后数据被缓存到内存中,再次读取就便宜了。

问题来了: 在柏林硬分叉之前,EVM只能“被动”感知访问顺序。如果一笔交易涉及多个合约,且这些合约在交易执行过程中被反复调用,EVM会自动将后续访问标记为“暖”。但如果是预编译合约(比如用于椭圆曲线配对的0x08地址)或者多层代理合约,执行路径极其复杂,EVM的“自动暖化”机制经常失灵——因为有些地址是在交易执行中途才被首次触发的,而一旦触发,它就已经是“冷”的,无法享受“暖”的折扣。

类比: 想象你开车进一个陌生小区,第一次进大门要登记(2,600 Gas),之后保安认识你了,每次进出只需挥手(100 Gas)。但如果你这趟车要先去A栋拿钥匙,再去B栋取文件,最后回C栋交还钥匙——如果小区保安系统不“预登记”B栋和C栋,你每到一个新楼都要重新登记一次。

二、柏林硬分叉的核心:EIP-2930与“预登记通行证”

EIP-2930引入了一个新的交易类型:0x01类型交易。它允许交易发送者在广播交易时,主动附上一份“访问列表”,列出这笔交易预计会触碰的所有地址和存储槽。

当这份列表被提交后,EVM在交易执行开始前,就会将这些地址和存储槽预先标记为“暖”。这意味着:

  1. 首次访问成本从2,600降至100
  2. 即使交易执行路径发生意外跳转,只要访问列表覆盖了相关地址,就能享受暖访问折扣。
  3. 对于复杂的多合约调用,比如Defi聚合器(如1inch、Paraswap),它们在一笔交易里可能调用5-10个不同合约,每个合约又读取多个存储槽——没有访问列表时,每个新合约地址都是“冷启动”,Gas消耗呈线性叠加;有访问列表后,所有地址在开局就被“暖化”,总Gas可降低约 10% - 30%(取决于具体合约逻辑)。

为什么说“动态”?——访问列表不是静态清单

注意一个细节:EIP-2930的访问列表是交易发送者手动构建的,但它是基于状态模拟(eth_call) 动态生成的。钱包前端(如MetaMask、Rabby)在用户点击“确认”之前,会先对交易进行本地模拟,分析出所有可能触碰的地址和存储槽,然后自动生成访问列表并附加到交易中。

关键点: 这个列表不是固定不变的。如果合约代码升级、存储布局改变,访问列表也会随之变化。所以它被称为“动态访问列表”——它随交易内容、合约状态、甚至链上时间的变化而动态调整。

三、哪些交易是“特定受益者”?——三个典型场景

1. 多签钱包与Gnosis Safe:一场“群聊”的降费革命

Gnosis Safe(现在叫Safe)是DAO金库最常用的多签钱包。执行一笔多签交易,通常需要:

  • 调用Safe合约的execTransaction函数
  • 该函数内部会调用目标合约(比如转账USDC)
  • 同时还会调用TokenCallbackHandler等辅助合约

在没有访问列表时,每个合约地址都是“冷”的,一次多签执行光地址冷访问就要消耗 2,600 × 3 ≈ 7,800 Gas。加上存储槽的冷访问(比如Safe的nonce、owner列表),总Gas经常突破 200,000

而柏林升级后,Safe钱包前端(或通过Safe API服务)会自动生成访问列表,将Safe合约、目标代币合约、回调处理器全部“预暖”。实测显示,单笔多签交易的Gas消耗可降低约15% - 20%。对于每天执行几十笔交易的DAO财库来说,一年节省的Gas费相当可观。

2. 跨链桥与Layer2:降低“跨链验证”的隐形成本

像Hop Protocol、Across这样的跨链桥,用户在L1上提交跨链请求时,合约需要验证另一条链上的Merkle Proof。这通常涉及:

  • 调用预编译合约(如0x08用于BLS签名验证)
  • 读取多个存储槽来验证状态根

预编译合约的冷访问成本极高,且无法被EVM自动“暖化”(因为它们不在普通合约的存储路径上)。EIP-2930的访问列表可以显式包含预编译地址,从而将每次预编译调用的Gas从2,600降至100。对于需要多次配对的ZKP验证(比如StarkNet的L1验证器),这项优化尤为关键。

3. 复杂DeFi交互:聚合器与闪电贷的“省油模式”

想象你在1inch上通过闪电贷完成一次“借-换-还”操作:

  • 调用闪电贷合约(如dYdX或Aave V3)
  • 调用Uniswap V3的SwapRouter
  • 调用Curve的Pool合约
  • 最后还款

没有访问列表时,这4个合约地址的冷访问成本就是 2,600 × 4 = 10,400 Gas。加上每个合约内部存储槽的冷访问(比如Pool的balances映射、Router的factory地址),总冷访问成本可能超过 30,000 Gas

而访问列表可以将这些地址和关键存储槽全部“预暖”,使冷访问成本几乎归零。根据Paraswap的公开技术博客,启用EIP-2930后,其聚合路由的Gas成本平均下降了 8% - 12%,对于大额交易,节省的Gas费用可能超过交易价值的0.5%。

四、柏林硬分叉与EIP-1559的“组合拳”:为什么伦敦升级离不开柏林?

很多人只记得伦敦升级(EIP-1559)引入了基础费销毁机制,却忽略了柏林升级为伦敦铺路的关键作用。

EIP-1559改变了Gas费的定价模型,但没有改变Gas的计量单位。也就是说,即使基础费被销毁,每笔交易消耗的Gas数量(Gas Used)依然取决于EVM的指令成本。如果柏林没有降低特定交易的Gas用量,伦敦升级后,用户依然要为复杂的多合约交互支付高昂的Gas费(只是从“矿工费”变成了“销毁费”)。

更关键的是: EIP-1559的maxFeePerGasmaxPriorityFeePerGas字段,与EIP-2930的accessList字段是兼容共存的。一个0x02类型交易(伦敦升级引入的Type 2交易)可以同时包含访问列表。这意味着:

  • 用户支付更低的基础费(因为Gas用量下降)
  • 同时享受访问列表的折扣
  • 矿工(验证者)也能从更高效的交易执行中受益(因为状态加载次数减少,节点压力降低)

可以这么说: 柏林硬分叉是“节流”,伦敦硬分叉是“定价”。没有前者,后者的价格改革无法充分释放红利。

五、动态访问列表的“天花板”与“未竟之业”

尽管EIP-2930效果显著,但它并非万能药。有几个现实瓶颈:

1. 钱包支持度参差不齐

MetaMask直到2022年才在部分版本中默认启用访问列表生成,而一些轻量级钱包(如Frame、Tally)至今未完全支持。用户如果使用不支持访问列表的钱包,就无法享受折扣。

2. 存储槽的“过度预暖”可能适得其反

访问列表如果包含太多不必要的存储槽,会导致交易数据本身变大(每多一个存储槽需额外支付约 1,900 Gas 的数据成本)。如果钱包的模拟引擎不准确,生成的访问列表可能比冷访问更贵。这需要钱包开发者精心调优。

3. 与未来EIP-7702的衔接

2024年提出的EIP-7702(账户抽象新方案)试图将EOA地址临时升级为智能合约,这同样涉及访问列表的交互。柏林留下的“动态预暖”思想,正在被纳入更宏大的账户抽象叙事中。

4. 对L2的间接影响

在Optimism、Arbitrum等L2上,由于数据可用性成本(Calldata)占主导,访问列表带来的EVM执行成本降低相对次要。但在zkSync、StarkNet这类执行层与数据层分离的系统中,访问列表仍然可以帮助降低证明生成时的状态访问成本。

六、实操指南:如何手动构造访问列表交易?

如果你是一个进阶用户,想自己手动附加访问列表,可以这样做(以ethers.js为例):

javascript const tx = { to: targetContract, data: calldata, accessList: [ { address: targetContract, storageKeys: [ "0x0000...0001", // 某个存储槽 "0x0000...0002" ] }, { address: "0x08", // 预编译合约 storageKeys: [] // 预编译合约无存储槽 } ] };

注意: 手动构造时,必须确保storageKeys是32字节的十六进制字符串。你可以通过eth_getStorageAt查询合约的存储布局,或者使用debug_traceTransaction分析历史交易来获取真实访问的存储槽。

但更推荐的做法是使用第三方库,如@ethersproject/providersresolveName配合eth_estimateGas,或者使用hardhathardhat-tracer插件自动生成访问列表。

七、从柏林到坎昆:动态访问列表的“精神续作”

柏林硬分叉距今已近三年,但它的技术思想从未过时。2024年3月激活的坎昆升级(EIP-4844)引入了Blob数据,大幅降低了L2的Calldata成本。但Blob交易本身也需要访问列表吗?答案是——不需要,因为Blob数据不在EVM状态中,而是独立的临时存储。

然而,EIP-4844的预编译合约BLOBHASH(地址0x0a)在L2欺诈证明中会被频繁调用。如果未来L1上的验证合约需要读取多个Blob哈希,那么EIP-2930的访问列表依然能派上用场。

更前沿的视角: 动态访问列表与“状态过期”(State Expiry)提案(如EIP-6800)存在天然协同。状态过期后,冷访问成本会进一步上升(因为可能需要从归档节点拉取数据),而访问列表的“预暖”机制将成为缓解这一痛点的核心工具。

八、结语:Gas优化是一场永不停歇的“军备竞赛”

柏林硬分叉的访问列表,看似只是一个“小优化”,但它揭示了以太坊Gas模型的一个深层哲学:所有成本都源于状态访问的不可预测性。动态访问列表将这种不可预测性部分转化为可预测的“预声明”,让交易发送者与EVM之间达成一种“成本契约”。

对于普通用户,你无需理解storageKeys的字节码,只需在钱包里看到Gas费比之前低了10% - 20%,这就是柏林分叉的胜利。

对于开发者,如果你在构建复杂的多合约交互,请务必检查你的钱包库是否支持accessList参数。如果不支持,你可能正在每个月默默多付几百万Gas。

最后,记住这个数字:2,600 vs 100。这不仅是Gas单位的差异,更是以太坊从“蛮力执行”走向“精细规划”的分水岭。下一次当你在Gas Tracker上看到一笔低于预期的费用时,不妨想想——这背后可能有一份精心设计的动态访问列表,正在替你无声地节省每一颗“聪”。

版权申明:

作者: 虚拟币知识网

链接: https://virtualcurrency.cc/core-concept/dynamic-access-list-berlin-hard-fork-gas-cost.htm

来源: 虚拟币知识网

文章版权归作者所有,未经允许请勿转载。

关于我们

 Ethan Carter avatar
Ethan Carter
Welcome to my blog!

最新博客

标签