EIP-2930:被低估的以太坊升級——存取清單交易完整解析
說到以太坊的 EIP,多數人只記得 EIP-1559 這個明星。但其實同一批升級裡還有另一個提案,雖然關注度低很多,卻帶來了根本性的改變。它就是 EIP-2930。這篇文章深入解析存取清單交易的技術細節,包括 EIP-2718 交易類型信封、EIP-2929 狀態存取 Gas 成本、以及存取清單如何實際降低 Gas 費用。同時探討 EIP-2930 對 ERC-4337 帳戶抽象和未來 EIP-7702 的深遠影響。
EIP-2930:被低估的以太坊升級——存取清單交易完整解析
說到以太坊的 EIP,多數人只記得 EIP-1559 這個明星。倫敦升級那年,1559 搶盡了所有風頭,彷彿以太坊的費用市場改革就靠這一個提案了。
但其實同一批升級裡還有另一個提案,雖然關注度低很多,卻帶來了根本性的改變。它就是 EIP-2930。
這傢伙到底做了什麼?簡單說:它讓交易發送前可以「預先告知」要存取的資料,驗證者因此能提前準備,大幅節省 Gas。概念類似搬家前先列清單,讓師傅知道沙發在哪、鋼琴在哪,比到了現場一件件指給他看有效率多了吧?
今天就來把 EIP-2930 的技術細節全部拆開來說。
EIP-2930 之前的世界:EIP-1559 的小兄弟
要理解 EIP-2930,得先知道它是什麼上下文裡誕生的。
Berlin 升級套餐
2021 年 4 月的 Berlin 升級包含四個 EIP:
- EIP-2565:ModExp Gas 計算優化
- EIP-2718:交易類型信封(Typed Transaction Envelope)
- EIP-2929:狀態存取 Gas 成本提升
- EIP-2930:存取清單交易
EIP-1559 其實是倫敦升級(2021 年 8 月)的成員,不是 Berlin 的。Berlin 升級的四個提案都是在為 1559 做準備,確保費用市場改革能夠順利運作。
當時的背景問題
在 EIP-2930 之前,每次交易執行都要重新「摸索」需要的資料。智慧合約可能存取任何儲存槽,但驗證者不知道你要用哪些,只能等你用到時現場讀取。
這導致幾個問題:
冷儲存存取費用高:讀取從未接觸過的儲存槽,要付出較高的 Gas。因為驗證者需要真的去磁碟讀取,不能靠快取。
重複存取也收費:即使同一個值被多人讀取過,每次讀取都收費,沒有減免。
交易大小限制:傳統交易格式比較固定,擴展性有限。
EIP-2930 就是要解決這些問題。
存取清單(Access List)是什麼?
核心概念很直白:交易發送時附帶一份「我要用到哪些地址和儲存槽」的清單。
格式長這樣
{
address: "0x1...", // 要存取的合約位址
storageKeys: [ // 要存取的儲存槽列表
"0x0...", // 第一個槽
"0x1...", // 第二個槽
// ...
]
}
一筆交易可以宣告多個合約位址,每個位址下可以列出多個儲存槽。
實際例子
假設你要在 Uniswap 把 ETH 換成 USDC。執行時可能需要:
// 典型 Uniswap V2 swap 需要存取的位址和槽
{
address: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", // Uniswap V2 Router
storageKeys: [
"0x0000...", // 工廠位址
"0x0001...", // 工廠某個狀態
]
},
{
address: "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc", // USDC/ETH 交易對
storageKeys: [
"0x0000...", // 準備金 1
"0x0001...", // 準備金 2
]
},
{
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC 合約
storageKeys: [
"0x0000...", // 總供給量
]
}
提前告知這些,驗證者就能預先載入資料,大幅降低處理成本。
EIP-2718:交易類型信封
在談 EIP-2930 的技術實現之前,需要先了解 EIP-2718。
為什麼需要交易類型?
傳統以太坊交易的 RLP 編碼格式是固定的:
[nonce, gasPrice, gasLimit, to, value, data, v, r, s]
這九個欄位的意義和位置都寫死在黃皮書裡。想擴展?只能發新版本的交易,但舊節點不認識怎麼辦?
EIP-2718 定義了一個信封機制:
TransactionType || TransactionPayload
第一個位元組是「交易類型 ID」,後面的內容根據類型有不同的解釋。
好處:
- 新節點能處理新類型交易
- 舊節點遇到不認識的類型直接跳過(不廣播)
- 定義新交易格式完全不需要改舊節點
交易類型註冊表
EIP-2718 建立了簡單的類型註冊約定:
| 類型 ID | 用途 |
|---|---|
| 0x0 | 傳統交易(Legacy) |
| 0x1 | EIP-2930 存取清單交易 |
| 0x2 | EIP-1559 費用市場交易 |
| 0x3+ | 未來擴展預留 |
這個設計允許往後繼續增加新的交易類型,不用擔心格式衝突。
EIP-2930 交易格式
EIP-2930 定義的新型交易,格式如下:
# EIP-2930 交易結構
rlp([
chainId, # 鏈 ID(1 = 主網)
nonce, # 發送者交易計數
gasPrice, # 單價(類似傳統交易)
gasLimit, # Gas 上限
to, # 目標位址(空 = 部署合約)
value, # 轉帳金額
data, # 交易資料
accessList, # 存取清單
yParity, # v 值(用於簽章恢復)
r, # 簽章 r 值
s # 簽章 s 值
])
相比傳統交易的九個欄位,多了三個新成員:
chainId:防止跨鏈 replay 攻擊accessList:存取清單yParity:用 0 或 1 取代原本的 v 值
簽章變化
EIP-2930 使用 EIP-155 的簽章格式來防範 replay:
v = chainId * 2 + 35 + yParity
對主網(chainId=1)來說:
- yParity=0 → v=36
- yParity=1 → v=37
這確保 EIP-2930 交易只能在正確的鏈上執行。
Gas 計算的變化
這是 EIP-2930 最核心的部分:Gas 怎麼省?
存取清單的 Gas 折扣
EIP-2929 定義了狀態存取的 Gas 成本:
| 存取類型 | 成本 | 說明 |
|---|---|---|
| Cold 存取(首次接觸) | 2100 / 2600 | 第一次讀取合約/儲存槽 |
| Warm 存取(重複接觸) | 100 / 100 | 在最近區塊中被存取過 |
Cold = 冰的,要從磁碟讀取。Warm = 熱的,還在記憶體快取裡。
存取清單的減免邏輯
當交易宣告了存取清單後:
宣告的位址:視為 Warm,正常存取成本 100 Gas
宣告的儲存槽:
- 如果不在快取:首次 Cold 存取改收 Cold+100(2100+100 或 2600+100)
- 如果已在快取:維持 Warm 成本
未宣告的存取:正常收費,無法享受折扣
實際計算示例
假設一筆交易執行時:
// 沒有存取清單
讀取合約 A 的槽 X(首次) → 2600 Gas
讀取合約 B 的槽 Y(首次) → 2600 Gas
執行合約邏輯 → 50000 Gas
─────────────────────────
總計:31200 Gas
// 有存取清單
存取清單宣告:[A, X] 和 [B, Y]
讀取合約 A 的槽 X(已宣告) → 100 + 100 = 200 Gas
讀取合約 B 的槽 Y(已宣告) → 100 + 100 = 200 Gas
執行合約邏輯 → 50000 Gas
─────────────────────────
總計:20400 Gas
節省超過 30%!在複雜的 DeFi 交易中,存取清單往往能省下更多。
EIP-2930 與 EIP-1559 的關係
很多人搞混這兩個 EIP 的定位。
EIP-1559:費用市場改革
- 引入 Base Fee 動態調整機制
- Base Fee 燃燒,ETH 通縮
- 用戶用 Priority Fee 搶優先權
不包含存取清單
EIP-2930:交易格式擴展
- 定義存取清單交易類型
- 允許預先宣告存取範圍
- 配合 EIP-2929 提供 Gas 折扣
不涉及費用市場
為什麼要分開?
設計上的考量:
- 解耦合:將費用市場和交易格式改為獨立變更
- 漸進式部署:EIP-2930 在 Berlin(2021.4),EIP-1559 在倫敦(2021.8)
- 向後相容:舊節點可以處理新格式
實務上,EIP-2930 為 EIP-1559 交易提供了底層支援。倫敦升級後,你發送的 1559 交易實際上底層也遵循 2930 的信封格式。
誰在使用存取清單?
瀏覽器錢包
多數現代錢包(MetaMask、Trezor Suite、Rabby)現在發送交易時都會幫你構造存取清單。
MetaMask 的實際行為:
- 估計交易需要的存取位址
- 查詢常見合約的熱門儲存槽
- 自動生成存取清單
開發者層面
如果你用 ethers.js 或 viem 發送交易,庫已經幫你處理好了:
// ethers.js 會自動添加存取清單
const tx = await contract.function(params, {
// 這裡 ethers 會幫你估算並添加存取清單
});
console.log(tx.accessList);
// [
// {
// address: "0x...",
// storageKeys: ["0x...", "0x..."]
// }
// ]
RPC 節點
Erigon(原 TurboGeth)和 Nethermind 節點對存取清單有優化處理。Geth 雖然也支援,但優化程度較低。
存取清單的限制
EIP-2930 不是銀彈,有些情況下效果有限:
無法完全預測
智慧合約執行的分支可能無法事先知道:
function execute(uint256 choice) external {
if (choice == 0) {
// 讀取合約 A
} else {
// 讀取合約 B
}
}
如果你選項 0,卻宣告了 B 的存取,浪費。如果選項 1,宣告了 A,也浪費。存取清單的準確性取決於對合約邏輯的理解程度。
過度宣告的問題
有些工具為了省麻煩,直接宣告大量常見位址和槽,反而增加交易大小(calldata),抵消了 Gas 節省的優勢。
calldata 的 Gas 成本是每 byte 16 gas(cold),如果宣告太多無用的存取,反而得不償失。
與 EIP-1559 的取捨
EIP-1559 的 Priority Fee 機制已經能有效控制等待時間。對多數用戶來說,存取清單的好處可能不明顯。但對大型 DeFi 操作、機構交易、批量交易,累積下來節省的就相當可觀了。
EIP-2930 的技術深水區
簽章處理
EIP-2930 的簽章格式與傳統交易不同。需要注意的是,外部簽章(off-chain signing)時要注意這點:
// 構造 EIP-2930 交易
const tx = {
type: 1, // EIP-2930 類型
chainId: 1,
nonce: 5,
gasPrice: 30000000000, // 30 gwei
gasLimit: 200000,
to: "0x742d35Cc6634C0532925a3b8D4C9B0d8a8f6b123",
value: 0,
data: "0x...",
accessList: [
{ address: "0x...", storageKeys: ["0x..."] }
],
yParity: 0,
r: "0x...",
s: "0x..."
};
簽章的 r, s 值仍然使用 secp256k1 橢圓曲線,但 yParity 取代了原本的 v 值來判斷簽章恢復。
交易驗證順序
節點收到 EIP-2930 交易後,驗證順序:
- 格式檢查:確認交易類型、長度、編碼正確
- 簽章驗證:使用 EIP-155 公式恢復發送者
- 鏈 ID 驗證:確保交易發往正確的網路
- Nonce 檢查:匹配發送者當前 nonce
- 餘額檢查:確保能支付 Gas
- Gas Limit 檢查:不超過區塊上限
- 存取清單預處理:將宣告的位址加入快取
注意存取清單的預處理是在所有基本檢查通過之後才執行的。
EIP-2930 的後續影響
EIP-2930 雖然低調,但為後續發展奠定基礎:
EIP-3074(未實現):這個提案打算讓 EOA 能夠委托執行權力給合約,類似一個「授權跳板」。它的設計就建立在存取清單的技術之上。
EIP-7702(2026 Pectra):EOA 臨時變身合約帳戶,這個提案某種程度上是 3074 的進化版,同樣依賴存取清單的底層機制。
所以 EIP-2930 不只是一次 Gas 優化,它是為未來更激進的帳戶改造預留的接口。
實戰:如何構造存取清單
使用 ethers.js
import { ethers } from "ethers";
const provider = new ethers.providers.JsonRpcProvider("...");
const wallet = new ethers.Wallet("0x...", provider);
// 構造帶存取清單的交易
const tx = {
to: "0x...", // Uniswap Router
value: ethers.utils.parseEther("1.0"),
// ethers 會自動估計存取清單
};
const populatedTx = await wallet.populateTransaction(tx);
console.log("存取清單:", populatedTx.accessList);
手動構造(進階)
const accessList = [
{
address: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
storageKeys: []
}
];
const tx = {
type: 1,
chainId: 1,
accessList: accessList,
// ... 其他欄位
};
工具推薦
- Tenderly:可以模擬交易並顯示完整 Gas 消耗
- Etherscan:交易詳情頁面可以看到實際使用的存取清單
- eth.call 加上 accessList 參數:RPC 測試
常見問題
Q: 普通轉帳需要加存取清單嗎?
不需要。EOA 對 EOA 的轉帳不涉及合約存取,加存取清單反而增加開銷。
Q: EIP-2930 和 EIP-1559 哪個先實施?
EIP-2930 先(Berlin 升級,2021 年 4 月),EIP-1559 後(倫敦升級,2021 年 8 月)。
Q: 存取清單會讓交易變大嗎?
會的。calldata 要多承載存取清單的資料。不過對於複雜交易,省下來的 Gas 通常比額外花費的多。
Q: 存取清單可以加快交易確認速度嗎?
不能直接加速,但可以省 Gas。速度主要由 Gas 單價和網路擁堵程度決定。
結語
EIP-2930 是一個「幕後英雄」型的提案。沒有 1559 那樣戲劇性的 Base Fee 燃燒機制,沒有那麼多媒體報導,但它實際上改變了交易傳輸的方式,為未來的協議升級預留了空間。
下次你用 MetaMask 發送 DeFi 交易時,交易能被順暢執行,Gas 計算能這麼精確,存取清單功不可沒。
理解這些底層機制,不只考試能用,在 debug 複雜交易、分析 Gas 最佳化、評估 Layer 2 方案的底層時,都會派上用場。
延伸閱讀
資料截止日期:2026 年 3 月
相關文章
- 以太坊生態應用案例實作完整指南:DeFi、質押、借貸與錢包交互 — 本文提供以太坊生態系統中最常見應用場景的完整實作範例,涵蓋去中心化金融操作、質押服務、智慧合約部署、錢包管理和跨鏈交互等多個維度。所有範例均基於 2026 年第一季度最新的協議版本,並包含可直接運行的程式碼和詳細的操作流程說明。
- 以太坊的燃料:以太幣(ETH)的技術、經濟學與實務完全指南 — 本文深入解析 ETH 的技術本質和經濟機制,超越表面的「加密貨幣投資」框架。涵蓋 Gas 機制的底層原理、EIP-1559 對費用市場的改革、錢包與帳戶模型的差異、交易的生命週期、質押機制的激勵設計、以及錢包安全的最佳實踐。適合想要深入理解以太坊系統運作原理的中級讀者。
- 以太坊 AI 代理與 DePIN 整合開發完整指南:從理論架構到實際部署 — 人工智慧與區塊鏈技術的融合正在重塑數位基礎設施的格局。本文深入探討 AI 代理與 DePIN 在以太坊上的整合開發,提供完整的智慧合約程式碼範例,涵蓋 AI 代理控制框架、DePIN 資源協調、自動化 DeFi 交易等實戰應用,幫助開發者快速掌握這項前沿技術。
- EIP-7702 帳戶抽象完整技術深度分析:從協議設計到錢包生態全景透視 — EIP-7702 是以太坊 Pectra 升級中引入的核心改進提案,為外部擁有帳戶(EOA)提供了臨時執行智慧合約程式碼的能力。本文從密碼學原理、網路共識、智慧合約設計、錢包開發等多個維度,提供 EIP-7702 的完整技術分析。我們深入探討這項協議的設計動機、技術實現機制、與 ERC-4337 的競合關係、錢包生態的適配現況,以及這項技術對以太坊未來發展的深遠影響。涵蓋完整的技術實現原理、开发者遷移指南、錢包生態適配狀況的深度分析,以及 Gas 費用結構變化與經濟激勵機制的完整分析。
- EIP-7702 帳戶抽象完整指南:從技術原理到實際部署的深度解析 — 本文深入解析 EIP-7702 與 ERC-4337 的核心差異。涵蓋帳戶模型的歷史演進、EIP-7702 的運作原理與交易格式修改、讓 EOA 臨時變身智能合約的技術實現、以及常見的應用場景(臨時多簽、延時交易、社交恢復)。並提供從 ERC-4337 到 EIP-7702 的遷移策略、安全考量、以及未來演進方向。
延伸閱讀與來源
- Ethereum.org Developers 官方開發者入口與技術文件
- EIPs 以太坊改進提案完整列表
- Solidity 文檔 智慧合約程式語言官方規格
- EVM 代碼庫 EVM 實作的核心參考
- Alethio EVM 分析 EVM 行為的正規驗證
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!