EIP-4337|Standards Track: ERC|狀態 Final|建立 2021-09-29|Requires: EIP-712, EIP-7702
作者:Vitalik Buterin、Yoav Weiss、Dror Tirosh、Shahaf Nacson、Alex Forshtat、Kristof Gazso、Tjaden Hess|授權 CC0
規格原文:https://eips.ethereum.org/EIPS/eip-4337

🎯 什麼情境該想到我

當你「要讓帳戶自己帶驗證邏輯」——多簽、社交回復、自訂簽章演算法、代付 gas、用代幣付手續費——的時候。
一句話定位:帳戶抽象,但完全不改共識層

⚙️ 怎麼用(步驟 / 公式)

整條路徑:不是交易,是 UserOperation

使用者 → UserOperation → 專屬 mempool → Bundler 打包
      → entryPoint.handleOps(ops[], beneficiary) → 上鏈

刻意不叫 transaction,避免混淆。它像交易一樣有 tocalldatanoncesignature/gas 欄位,但 signature 的用法不由協議定義,而是由帳戶合約自己決定——這就是「抽象」的所在。

六個角色

角色職責
Sender發出 UserOperation 的智能合約帳戶(SCA)
EntryPoint單例合約,執行整批 UserOperation。bundler 應白名單化支援的 EntryPoint
Bundler收集 UserOperation、組成 handleOps() 交易送上鏈。本身是 block builder,或透過 mev-boost 之類的 PBS 基礎設施
Paymaster代付手續費的輔助合約
Factory需要時部署新的 sender 合約
Aggregator讓多個 UserOperation 共用一次驗證(完整設計不在本規格範圍)

帳戶要實作的介面

interface IAccount {
    function validateUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external returns (uint256 validationData);
}

userOpHash 是對 userOp(不含 signature)、EntryPoint、chainId 的雜湊。帳戶:

  • MUST 驗證呼叫者是可信的 EntryPoint。
  • MUST 驗證簽章對 userOpHash 有效。
  • ⭐ 簽章不符時 SHOULD 回傳 SIG_VALIDATION_FAILED(1)而不是 revert;其他錯誤 MUST revert。
  • ⭐ 而且 SHOULD 不要提早 return,要跑完正常流程——這兩條都是為了讓 gas 估算能運作
  • MUST 付給 EntryPoint 至少 missingAccountFunds(可能是 0)。付多了可用 withdrawTo 取回。

回傳值是 packed 的三段:aggregator/authorizer(0=簽章有效,1=失敗,其他=aggregator 地址)+ validUntilvalidAfter(各 6 bytes 時間戳,0 表示無限)。
要改用區塊高度表達有效區間,兩個值的最高位都要設 1;時間戳與區塊高度不能混用。

半抽象 nonce:192-bit key + 64-bit sequence

把單一 uint256 nonce 拆兩段,getNonce(sender, key) 查詢。
每個 key 各自維持一條遞增序列 → 同一個帳戶可以有多條互不阻塞的操作流,而不是被單一遞增 nonce 卡住排序。

防重放

signature MUST 依賴 chainid 與 EntryPoint 地址——否則會被跨鏈重放,或被不同版本的 EntryPoint 重放。

Paymaster 流程

paymasterAndData 非空時,EntryPoint 走不同流程:

  1. 驗證迴圈中額外檢查 paymaster 在 EntryPoint 的 ETH 存款是否足夠。
  2. 呼叫 validatePaymasterUserOp 確認它願意付。此時 validateUserOpmissingAccountFunds0(帳戶存款不會被動用)。
  3. validatePaymasterUserOp 回傳非空的 context,主執行呼叫之後 MUST 呼叫 postOp

⭐ 模擬(Simulation)—— 整個安全模型的核心

規格講得很清楚為什麼需要它:

  • 一般交易的檢查(ecrecover、nonce、餘額、gasLimit、chainId)不依賴 EVM 狀態,別人的交易改不掉。
  • UserOperation 的驗證依賴 EVM 狀態,會被同批或其他交易改掉。

所以 bundler 必須做離線的 view/trace call,跑 EntryPoint 的驗證段並強制 opcode 與 storage 存取規則。目的是讓驗證邏輯 sandboxed、與同 bundle 的其他 operation 隔離
模擬 revert,bundler MUST 丟棄該 UserOperation。

打包時 bundler MUST

  • 排除會存取同 bundle 中其他 UserOperation 之 sender 地址的 op。
  • 排除會存取同 bundle 中由 factory 新建地址的 op。
  • 逐一累計每個 paymaster 的餘額,確保足以支付所有使用它的 op。

上鏈前 SHOULD 用最大 gas 跑 debug_traceCall 再驗一次規則。

信譽與質押

惡意 paymaster 可以對系統發動 DoS。緩解方式:bundler 應對其服務的合約建立信譽系統,paymaster 要嘛限制自己的 storage 用量、要嘛質押。完整的信譽系統規格不在本提案範圍。
規則太嚴而卡到合法用途時,逃生口是 alternative mempool(放寬規則的另一組 P2P 網路),但其推廣程序同樣不在本規格範圍。

🧪 我實際套用的紀錄

  • 2026-08-27:(待填)

⚠️ 注意 / 什麼時候不適用

1. EntryPoint 是被刻意集中的信任點

規格自己在 Security Considerations 承認:EntryPoint 需要審計與形式驗證,因為它是所有 ERC-4337 的中央信任點
論證是這樣的取捨——把風險集中在一個合約,換取每個帳戶要驗證的東西變得很小(只要驗 validateUserOp 的「查簽章、付費用」邏輯,以及其他函式有 msg.sender == ENTRY_POINT 把關)。整個生態的稽核總量因此下降。

形式驗證要涵蓋的兩個主要宣稱:

  • 不可任意劫持:EntryPoint 只會用 userOp.calldata 呼叫 sender,且只在該 sender 的 validateUserOp 通過之後。
  • 不可抽乾手續費:驗證通過就必須真的做出那個呼叫。

2. 「不改共識層」的代價(我的補註)

規格開宗明義的目標是不動共識層——因為共識層開發正專注於擴展性,短期不會有機會塞新交易型別。代價是把複雜度整包推到鏈下基礎設施:你需要 bundler 網路、需要信任 EntryPoint 這一個合約、驗證邏輯被 opcode 與 storage 規則綁死、還要一套規格自己都說「不在範圍內」的信譽系統。
這不是「更好的帳戶」,是「用鏈下複雜度換不用等硬分叉」。

3. 最容易寫錯的一條:簽章失敗要回 1、不要 revert

validateUserOp 在簽章不符時 SHOULD 回傳 1 而不是 revert,而且不要提早 return。理由是 gas 估算需要跑完整條路徑。直覺會寫成 require(sig ok)——那會讓估算失效。

4. 有效區間不能混用時間戳與區塊高度

validUntilvalidAfter 要嘛都是時間戳、要嘛都是區塊高度(最高位設 1),不能一邊一個。

5. 規格明確排除在外的部分

Aggregator 的完整設計、canonical mempool 的完整規則、信譽系統的完整規格、alternative mempool 的推廣程序——都不在這份文件裡。真要實作得再找對應的規範或既有實作。

6. 它與 EIP-7702 的關係

本規格 Requires: EIP-7702factory 欄位可放 0x7702 旗標代表 EIP-7702 帳戶。規格在動機處明說:4337 的目標是完全不需要使用者另外持有 EOA,而現況的智能合約帳戶與 EIP-7702 都還需要。

🔗 相關工具