原生抽象帳戶:EIP-8141 Frame Transaction — part I

EthTaipei 发布于 2026-06-11 阅读 107

本文深入解析EIP-8141提出的Frame Transaction,这是以太坊账户抽象的最终方案。

本篇文章內容由AI與作者共同編寫,最終的產出由作者審閱及潤飾

frame transaction 的介紹將分成兩部份,第一部分為 frame transaction 的基本架構介紹,第二部分會深入運作的細節與安全性的討論。

Generated by AI

起初會看到這個 EIP 是年初在看以太未來藍圖( https://strawmap.org/),看到 Hetoga 升級中有 “Native AA” ,這馬上勾起了我的好奇心,想說講了好久的抽象帳戶就這樣突然要上線了!不過大概隔一週原本寫著 “Native AA” 的區塊就被改成了 “Frame Transaction”。

引言:帳戶抽象的演進

這幾年抽象帳戶(Account Abstraction, AA)一直是關注的焦點,從最早的 EIP-86 到大規模落地的 ERC-4337,從 EOA 委託方案 EIP-3074 到程咬金 EIP-7702。每個解決方案比較像是圍繞在 EOA / 合約的這個架構上的替代方案,因為要做到原生抽象帳戶(Native AA)需要修改底層架構,是一項大工程。但隨著這幾年的升級,執行層有更多的功能且對於不同型態的交易更加有彈性(例如 EIP-2718),再加上未來後量子密碼學(Post-Quantum, PQ)的威脅,抽象帳戶誕生了演進之路的終點 — EIP-8141 Frame Transaction。

ERC-4337(2023 年) 是第一個大規模落地的方案。它選擇了一條務實的路 — 不動協議底層,在外面搭一整層鷹架。引入一個獨立的記憶體池與「打包者(Bundler)」網路:使用者把操作打包成 UserOperation,打包者收集並驗證這些操作後,再以一筆普通的 EOA 交易批次上鏈。這個架構讓多簽錢包、社交恢復、passkey 登入等功能更容易實作也更加普及,對合約錢包開發者來說也輕鬆了不少,不需要自己打造基礎建設。但這依然是沈重的基礎設施,打包者及 paymaster 開發耗時、維護上更是負擔,而最終只能依賴大型開發商所提供的服務。

EIP-7702 是一次漂亮的過渡方案。它讓 EOA 可以把一個智能合約的程式碼「借」到自己的地址上執行,不改變帳戶的根本性質。這意味著現有 EOA 無需遷移地址,就能享受批量交易、gas 贊助等好處。若沒有量子電腦的威脅,這個方案也足以應付現今大部分對抽象帳戶的需求。但因為交易的本質上仍然是 EOA,底層的 ECDSA 公私鑰仍然面臨量子電腦的威脅。

EIP-8141,是這場演進的終點。直接修改以太坊的底層架構,引入一種全新的交易類型 — Frame Transaction。打包者被協議原生取代,ECDSA 簽章不再是帳戶的唯一通行證,後量子密碼也第一次正式進入這個系統。

本文將從 frame transaction 的核心架構出發,依序剖析其執行模式、授權機制、gas 記帳,最後透過實際範例看清楚它如何改變日常的鏈上互動。

Frame Transaction 的核心架構

Frame transaction 架構

一筆交易,多個 Frame

要理解 frame transaction 為什麼長成這個樣子,得先了解傳統交易長什麼樣子。

傳統 EOA 交易的結構是這樣的:from(誰)、to(執行目的地)、data(做什麼)。這個結構把「是誰」、「做什麼」、「誰來付錢」三件事壓縮進同一個單一動作,而且三件事全部靠同一把私鑰。這在最簡單的場景下沒問題,但一旦你需要把它們拆開,比如讓別人幫你付 gas,或是一筆交易做多件事,就有點麻煩了。

EIP-8141 的設計選擇是回到根本: 把「驗證」、「執行」、「支付」明確地分成不同的 frame,每個 frame 各司其職,協議直接定義這些角色。一筆 frame transaction 可以包含一個 frames 陣列,目前允許最多 64 個 frame,可將每個 frame 視為獨立子交易,可以想像像是 MultiCall 合約可以一次執行多筆交易一樣。frame transaction 的欄位定義如下:

[chain_id, nonce, sender, frames, max_priority_fee_per_gas, max_fee_per_gas, max_fee_per_blob_gas, blob_versioned_hashes]

frames = [\
  [mode, flags, target, gas_limit, value, data],\
  [mode, flags, target, gas_limit, value, data],\
  ...\
]

交易類型代碼為 FRAME_TX_TYPE = 0x06。在整個組成中,比較值得注意的是 senderframes,其餘跟一般交易差不多。

# 開始之前,先釐清地址的定義 #

而在深入細節前,想先釐清每個「地址」所代表的意義,避免搞混主從關係。

Etherscan 的角度 來看一個交易來看 FromTo

  • 傳統交易To 就是要執行的目的地,例如 USDC 轉帳就是 USDC 的合約地址,去 Uniswap 交易就是 Uniswap 的合約地址。而在交易的欄位中是沒有 From 這個欄位的,From 是由簽章還原所得到的。
  • EIP-8141To 一樣是執行的目的地,但是在一個 EIP-8141 交易中可以有多個 frame,每個 frame 會有自己的執行目的地(frame.target),所以在這裡的 To 從單一的執行目的地變成了多個目的地。From 則與簽章分離,而是從 tx.sender 直接帶入,這代表我們可以帶入合約地址,使得合約是交易發起者 — From

接著從 合約的角度 切入:

  • 傳統交易tx.origin 是發送交易者,也就是上面的 From,如果是 EOA 發起的交易,就是 EOA 本人;若是透過 relayer 代送的,就是 relayer 的地址。msg.sender 單純就是上一個呼叫者。
  • EIP-8141:在 EIP-8141 中每個 mode 的情況不一樣,這邊先就一般的交易執行(SENDER mode)做說明。上面有提到 Fromtx.sender,所以 tx.origin就是 tx.sender ,而在交易執行的模式下 frame 的 caller 就是 tx.sender,所以被呼叫的合約(例如 USDC 合約)看到的 msg.sender 就是使用者地址,跟傳統 EOA 呼叫 USDC 時看到的完全一樣。這個設計讓現有的 DeFi 合約完全不需要修改就能支援 frame transaction — Uniswap、Aave 根本不需要知道 frame transaction 的存在。

但要注意一個重要變化:ORIGIN opcode 的語意被重新定義為「當前 frame 的 caller」,而不再是傳統意義上「發起整筆交易的 EOA」。所以在不同的模式下值也會不同:

  • SENDER mode(上述的一般的交易執行):ORIGIN = tx.sender
  • DEFAULT / VERIFY mode:ORIGIN = ENTRY_POINT (0xaa)

後面會再詳細介紹各種模式所代表的意義

這是一個對合約實作有影響性的變更,所有依賴 tx.origin == msg.sender 來判斷「是否為直接 EOA 呼叫」的合約都會受影響 — 因為在 EIP-8141 下 tx.sender 本身就可以是合約帳戶,這個檢查不再能區分「EOA 發起」和「合約帳戶發起」。

# 其他新增的結構細節 #

  • 獨立的 flags 欄位:這是一個專門的控制旗標欄位,用來設定該 frame 的特殊行為。位元 0 與 1 用來設定授權範圍(Approval scope),位元 2(值為 0x04)則用來設定原子批次(Atomic batch)。授權範圍與原子批次後面會在詳細介紹。
  • 原生的 value 欄位:最初的版本沒有這個欄位,是在經過社群的反應後才加入的。加了這個欄位 frame 就可以支援 ETH 轉帳,但有一個重要限制 — 只有交易執行模式(SENDER mode) 的 frame 可以帶非零的 value;這意味著在 SENDER frame 中可以直接傳遞 ETH,不再需要目標合約帳戶自己實作複雜的轉帳邏輯,大幅減輕開發負擔。
  • 預設 target:每個 frame 各自有自己的 target,若為 null 則預設為 tx.sender
  • Receipt 結構變化:由於 frame transaction 和 EOA 交易不一樣,不一定要由交易發起者支付手續費(可由 paymaster 代付),但是 payer 無法從交易靜態推斷,EIP-8141 在收據中明確加入 payer 欄位。

每個 frame 都有獨立的子收據,記錄執行狀態(成功/失敗)、實際用掉的 gas、與產生的 logs。這讓區塊瀏覽器可以清楚呈現每個 frame 的執行結果。

三種執行模式

frame transaction 有三種 mode,三種 mode 對應的是帳戶抽象裡三個不同的角色和信任邊界。

#VERIFY 模式:只讀取的驗證模式 #

目的在驗證簽章,確認交易的有效性。這個模式不能寫任何狀態,如同 STATICCALL 一樣,只能讀取和計算。這裡設計概念上跟 ERC-4337 一樣,在驗證階段不能去修改狀態或讀取外部的動態資訊,避免鏈下模擬成功但上鏈失敗。然後在驗證成功後需要呼叫 APPROVE,去設定 payer_approved 或是 sender_approved

APPROVE 是新增的 opcode,payer_approved sender_approved 分別對應到 paymaster 的授權跟使用者的授權,下一節會詳細介紹

背景補充:傳統交易的sig_hash 是怎麼運作的?

在深入探討為什麼 VERIFY frame 的 data 會有這些特殊設計之前,我們必須先理解以太坊底層是如何處理「交易簽章(Transaction Signature)」的。我們不會直接對一大包原始資料(如整筆交易的內容)進行簽名,而是遵循以下三個步驟:

  1. 序列化與雜湊(Hashing):先將交易的所有參數(如 nonce, to, value, gas_limit, data 等)使用 RLP 編碼,然後做一次 keccak256 雜湊計算。而這個雜湊的輸出值就代表這筆交易的 sig_hash(簽章雜湊)
  2. 私鑰簽名(Signing):使用者用自己的私鑰,對這個 sig_hash 進行數學運算,產生出簽章結果(即我們常聽到的 v, r, s 值)。
  3. 上鏈(Broadcasting):將算出來的簽章附加上去,形成一筆完整的交易廣播到網路上。

在傳統的交易結構中,v, r, s 是三個獨立的欄位。在計算 sig_hash 時,會先將這三個欄位留空,算出雜湊、簽完名後,再把值填進去。在傳統的交易 「被簽署的資料內容(data)」跟「簽章存放的位置(v, r, s)」是獨立分離的

然而到了 EIP-8141,為了支援任意的驗簽邏輯(如多簽、Passkey 或未來的後量子簽章),協議不再寫死固定的 v, r, s 欄位。所有的簽章資料、金主的授權憑證,現在都必須作為參數,塞進 VERIFY frame 的 data 欄位裡,交由合約去解析。這個「把簽章放進資料欄位」的結構改變,使得 data 欄位在計算 sig_hash 時會被自動省略,而原因有三層:

  • 循環依賴:因為 VERIFY frame 的 data 欄位包含了簽章本身,所以在計算「準備要被簽署的雜湊值」時,這個欄位是無法被決定的,因此必須將其省略。
  • Gas Sponsorship 工作流:將 data 從雜湊計算中排除,可以實現「不依賴簽署順序」的工作流程。這確保了使用者可以先對交易進行簽名,隨後 paymaster 再將自己的授權資料加入,而不需要使用者重新簽名。同時,由於 frame.target(指定誰來驗證,例如 paymaster 的地址)仍然被包含在簽章雜湊中,因此能確保惡意節點無法在傳輸過程中偷換 paymaster。
  • 未來的聚合驗證(Signature Aggregation):在核心開發者的會議中,確實特別討論了重構 EIP 編碼方式的需求,目的是為了確保在未來進行後量子簽章聚合時,聚合後的簽章並不會導致整筆交易的雜湊值發生改變。

這也帶來一個重要的安全含義:使用者的簽章內容不包含 data,所以 data 內容是可以被篡改的。因此像是匯率參數、費用上限等等收費參數,paymaster 不能仰賴使用者透過 data 提供,而是需要自己附上並簽名,讓鏈上合約可以驗證,以及避免他人竄改參數。

#SENDER 模式:以使用者身份執行 #

這個模式就是一般的合約呼叫,且 caller 是 tx.sender,所以呼叫任何合約時,對方看到的 msg.sender 就是使用者地址。這是向下相容的關鍵:Uniswap、Aave 這些合約完全不需要知道 frame transaction 的存在。

SENDER 模式有一個硬性前提:執行到該 frame 時,sender_approved 必須已經是 true,否則整筆交易無效。這個約束防止了顯而易見的冒名攻擊:如果沒有這個規則,任何人都可以構造一筆 frame transaction,把 tx.sender 欄位填成任意地址,用 SENDER frame 冒充那個地址去呼叫合約。先 VERIFY(通過簽章認證 sender 身份)、後 SENDER(以 sender 身份執行)的強制順序,確保了交易的執行必須有明確的授權基礎。

#DEFAULT 模式:協議的中立執行人 #

Remember me for faster sign in

這個模式也是一般的合約呼叫,但 caller 是 ENTRY_POINTaddress(0xaa)) — 協議定義的 虛擬地址,不是實際部署的合約。它存在的意義是為「既不是使用者、也不應該有任何自身利益」的操作提供一個中立的執行身份。典型用途有兩種:

  1. 帳戶部署(deploy frame):在 tx.sender 地址首次部署智能帳戶合約。由於此時 sender 尚未認證(因為 deploy frame 必須在 VERIFYframe 之前,後面 validation prefix 章節會介紹到),因此 caller 會被設定為 ENTRY_POINT 而不是 tx.sender 本身。
  2. Paymaster 的 post-op:在所有 SENDER frame 執行完畢後,paymaster 可以做退款結算、ERC-20 轉 ETH 之類的收尾工作。此時 caller 是 ENTRY_POINT 而不是 tx.sender,避免在做鏈下資訊搜集時誤以為是使用者的操作

三種 mode 的統整

與 ERC-4337 的 EntryPoint 差異:

  • ERC-4337 的 EntryPoint 是一個 真實部署 的合約,打包者把 UserOperation 傳給它,它在合約層實作驗證與執行。
  • EIP-8141 的 ENTRY_POINT 是一個 協議定義的虛擬地址,沒有程式碼、不能被 CALL,只作為 caller 身份標記。整個驗證與執行邏輯由協議本身處理。

核心:APPROVE 操作碼

理解了三種模式之後,APPROVE 是把它們串接起來的關鍵。

開始之前先定義:resolved_target,若 frame.target 有值,則 resolved_target 設為 frame.target,若沒有設定,則設定為 tx.sender

APPROVE 有一個 scope 參數(frame.flags 的頭兩個位元 0 跟 1),決定這次呼叫的有哪些同意授權:

  • APPROVE_PAYMENT (0x1):金主的授權 — gas 費用從這個地址扣除,設 payer_approved = true
  • APPROVE_EXECUTION (0x2):使用者的授權 — 驗使用者的簽名,驗證通過後,後續 frames 的執行都算這個使用者所呼叫,設sender_approved = true。此外 resolved_target 一定要是 tx.sender , 因為 APPROVEVERIFY frame 在呼叫,目的在驗證使用者的授權,所以執行的目標一定要是 tx.sender
  • APPROVE_PAYMENT_AND_EXECUTION (0x3):兩者同時設為 true(原子操作,不等於呼叫兩次 APPROVE

EIP-8141 把使用者跟金主兩個角色分開(如同 ERC-4337 paymaster 的設計),因此授權也分開處理。在驗證的最後透過 APPROVE opcode 來設定這兩個的授權狀況,它的行為類似 RETURN - 成功終止當前 frame 的執行。此外,payer_approvedsender_approved 的值在整筆交易是全域的,並且不能被重複設定,若已經設為 true 再設定一次就會 revert。

如果金主餘額不足,整個 frame revert。所有 frame 執行結束後,剩餘未用的 gas 才會退還給金主。這是「先預扣、後退款」的方式,跟傳統交易的「先扣 gas_limit × gas_price、後退差額」是一致的。

同理,APPROVE(APPROVE_PAYMENT_AND_EXECUTION) 會把以上三件事與「設定 sender_approved = true」一起完成。

# 執行順序約束 #

授權有嚴格的順序:必須先 sender_approved = true 確認使用者身份後,才能授權 paymaster 設定 payer_approved = true,不然會直接 revert。此外,設定 payer_approved會同時觸發三個動作:

  • tx.sender 的 nonce 遞增
  • 從金主的地址預扣交易的最大可能費用
  • 設定 payer_approved = true

而這個順序約束的意義為:

  • 對 Mempool 而言:節點可以在驗證使用者簽章失敗時立刻踢除整筆交易,不需要繼續執行後續的 paymaster 驗證,避免 DoS 的消耗。
  • 對 Paymaster 而言:當它呼叫 APPROVE(APPROVE_PAYMENT) 時,可以 100% 確信使用者的簽章驗證已通過,不需付「替一筆簽章無效的交易墊付費用」的風險。

# 呼叫者約束 #

呼叫 APPROVE 時有個限制:執行 APPROVE 的地址必須是 frame 的目標執行地址(frame.target) 本身(ADDRESS == resolved_target),否則會 revert。也就是說,不能設定 frame.target是合約 A,但是透過 STATICCALL 跑到 合約 B 去呼叫 APPROVE。這樣是避免無意間呼叫到惡意的合約而幫你亂授權。但 DELEGATECALL 就沒這個問題,因為 DELEGATECALL 仍在 caller 的 context 中,所以 ADDRESS 依然是 target 本身。

ENTRY_POINT = 0xaa 與新增的 APPROVE opcode 值 0xaa 剛好相同,原文有明確指出兩者在數值上的相等 沒有語意意義。不過都是 0xaa 讓人有 A ccount A bstraction 縮寫的猜想。

小結上面所介紹的內容,一個 frame transaction 的流程大概如下:

Frame Transaction 的流程

接下來的問題,就是這套設計該怎麼銜接到現在的執行層,對於 EOA 使用者該怎麼辦?

Default Code 與任意驗簽邏輯

EOA 的無縫升級:Default Code

frame transaction 的核心架構對智能合約帳戶來說完整且優雅,但有一個現實問題:以太坊上絕大多數的使用者現在都是 EOA,他們的地址沒有部署任何合約。如果 frame transaction 要求目標地址一定要有合約才能驗簽,那所有 EOA 使用者都得先部署帳戶合約才能用新功能,遷移成本巨大。

EIP-8141 用「預設程式碼(Default Code)」解決這個問題。當使用者既沒有合約也沒有 EIP-7702 委派時,協議不會拒絕呼叫,而是執行一段協議層面預先定義好的邏輯,效果就好像這個地址隱形地部署了一個標準的「迷你驗證合約」。

預設程式碼最重要的意義是: EOA 不需要部署任何合約,不需要遷移資產到新地址,就能直接享用 frame transaction 的所有好處 — gas 贊助、批量操作、ERC-20 付 gas、passkey 登入等。對 EOA 使用者而言,唯一的差異是錢包供應商必須支援 frame transaction 交易。

預設程式碼最上層邏輯

#DEFAULT 分支:直接 revert #

EOA 的預設程式碼不支援 DEFAULT 模式 — DEFAULT frame 的 caller 是 ENTRY_POINT,通常是給 paymaster 的 post-op 用的,不是 EOA 能觸發的場景。

#VERIFY 分支:簽章類型由data 決定 #

第一個 byte :

  • 0x00 代表 secp256k1,對應傳統錢包的簽章
  • 0x01 代表 P256(secp256r1),對應手機的 Passkey / Secure Enclave 簽章

預設程式碼內建支援了 P256,也就是時下最熱門 passkey 的簽章方式。使用者在手機上建立 passkey 時,Secure Enclave 自動產生一對 P256 金鑰,讓 passkey 公私鑰可以直接獲得一個地址 。此後這個帳戶的唯一憑證就是這把存在硬體裡的 P256 私鑰,根本不需要助記詞。

流程圖 2:預設程式碼 VERIFY 分支邏輯

值得注意的是, EIP-8141 本身並不直接引入後量子(PQ)安全的簽章方案。EIP-8141 真正的 PQ 意義在於:VERIFYframe 可以執行任意 EVM 程式碼來驗簽。今天可以是 secp256k1 或 P256,明天可以是 Dilithium 或 Falcon 等 PQ 方案。當未來引入 PQ 簽章預編譯合約時,合約帳戶只需要更新自己的驗簽邏輯,不需要任何協議升級。這就是規範所謂的「native off-ramp from ECDSA」:把選擇簽章方案的權力從協議下放給帳戶。

#SENDER 分支:EOA 的批量操作 #

EOA 的 SENDER frame 不只是「轉帳」,frame.data 是 RLP 編碼的呼叫清單 [[target, value, data], ...],可以在一 frame 內依序執行多個呼叫。這讓 EOA 在不部署任何合約的前提下,也能做批量操作(例如一次 approve + swap)。

流程圖 3:預設程式碼 SENDER 分支邏輯

小結

我們目前已經把 frame transaction 的骨架拼起來了。

一筆 frame transaction 不再是單一的「from / to / data」,而是由多個 frame 組成的陣列。協議透過三種 mode(VERIFYSENDERDEFAULT)把「驗證」、「執行」、「支付」三件事拆開,每種 mode 對應不同的信任邊界跟 caller 身份。串接這一切的核心是 APPROVE,它把使用者授權跟金主授權兩個角色明確分離,並有嚴格的順序(先 sender_approvedpayer_approved)。

最後 default code 讓現有 EOA 不需要部署合約就能無痛升級。 但骨架建好之後,還有不少執行細節值得深入,將會在下一篇文章介紹。

Special thanks to

Nic Lin

for reviewing and improving this post

參考資料:

相关文章

0 条评论