以太坊 Pectra 升級:EIP-7702 實用指南
作者:Cobo Global
以太坊主網即將迎來的 Pectra 升級是一個較大更新,一次性引入了多個以太坊改進提案(Ethereum Improvement Proposals, EIPs)。其中 EIP-7702 實現了對以太坊外部賬戶( Externally Owned Account, EOA )的重大改造,該提案模糊了 EOA 與合約賬戶(Contract Account, CA)的邊界,提供的新能力對普通用戶、各種基礎設施提供商、開發者都會產生重大影響。
近期 Pectra 已經在測試網中完成,預計很快就可以上線主網。本文將深入分析 EIP-7702 的實現,展示其可能帶來的機會與風險,為各類用戶、從業者提供參考。
EIP-7702 概述
EIP-7702 的實際標題為 EIP-7702: Set EOA account code 副標題 Add a new tx type that permanently sets the code for an EOA。這比較概括了介紹了這個提案的核心要素:提供了一種可以為 EOA 設置合約代碼的交易類型。
具體來說,這次提案引入交易類型為 SETCODETX_TYPE (0x04) 的交易,其數據結構如下:
rlp([chainid, nonce, maxpriorityfeepergas, maxfeepergas, gaslimit, destination, value, data, accesslist, authorizationlist, signatureyparity, signaturer, signature_s])
authorizationlist = [[chainid, address, nonce, y_parity, r, s], …]
相比於我們常見的 0x02 交易類型,主要變化是添加了 authorizationlist 字段。authorizationlist 中的每個元素表示進行一次地址代理的授權。其中:
- chain_id 為授權生效鏈 ID,用於防重放
- nonce 為授權方地址的 nonce,與普通交易 nonce 一致,也用於防重放
- address 為進行地址代理時指定的代理。
- y_parity, r, s 為簽名數據,通過 ecrecover 可以得到 authority 地址,即發起授權的 EOA 地址。
每個交易中可以包含多個上述授權。並且需要注意上述授權有獨立的簽名,與本體交易的簽名不同,因此可以實現對地址授權行為的 gas 代付。錢包服務商或者 App 開發者,可以為 authority 支付 gas 實現 EOA 的授權,而無須 authority 自身地址上保存 gas。
交易上鏈後,會將 authority 地址的 code 字段設置成對代理地址的 委託標識(Delegation Designation, DD)。DD 的形式如下:
0xef0100 || address
其中 0xef0100 為固定前綴,address 為代理的目標地址。這裡有一個細節,根據 EIP-3541,用戶無法通過常規的合約部署手段( to 為空的交易,create/create2 指令)部署 0xef 開頭的合約代碼。因此上述委託只有 EOA 才能發起,通過 0x04 交易完成。
委託完成後,所有針對 authority 的合約調用,均會使用 address 上的 code 作為 code,同時使用 authority 自身的 storage。使用體驗十分類似 ERC-1167 代理合約。
總結:EIP-7702 使 EOA 在保留原本發起交易能力的基礎上,同時具備 Proxy 合約的效果。用戶可以通過 SETCODETX_TYPE (0x04) 交易來設置、修改、移除 Proxy 的 Implementation 合約。
其他關於 EIP-7702 的技術細節可以閱讀提案原文。
EIP-7702 帶來的影響與機會
EIP-7702 是一項重大改變,對區塊鏈行業中的各個參與方都帶來了重大影響,也提供了許多新的機會。
合約錢包服務商
從提案本身的標題和實現機制中可以看出,EIP-7702 本身並不專門提供有關賬戶抽象(Account Abstraction, AA)的上層能力(如 gas 抽象,nonce 抽象, 簽名抽象等),只是提供了將 EOA 轉化成 Proxy 合約 的基礎能力。因此該提案並不與現行的各類合約錢包基礎設施(如 Safe, ERC-4337 等)相衝突。相反,EIP-7702 與現有的合約錢包可以幾乎無縫融合。允許用戶的 EOA 轉變成 Safe 錢包,ERC-4337 錢包。從而集成合約提供的多簽、gas 代付、批量交易、passkey 簽名等等功能。合約錢包提供商如果能快速、順滑地集成 EIP-7702,可以有效擴展用戶群體,提升用戶體驗。
DApp 開發者
由於 EIP-7702 對 AA 錢包的用戶體驗上有所提升,DApp 開發者可以考慮更大範圍的接入 AA 錢包,為用戶與 DApp 交互提供更便捷安全的體驗。如利用合約錢包的批量交易能力一次性完成多個 DeFi 操作。
另一方向 DApp 也可以考慮根據項目特性為用戶定制開發 Delegation 合約,為用戶提供專有的複雜合約交互功能。
資產托管方
對於交易所、資金托管方,通常需要管理大批量的地址作為其用戶的充幣地址,並定期進行資金歸集。傳統的資金歸集模式中使用 EOA 地址作為充幣地址,進行歸集時需要向充幣地址充值一定金額的 gas,並由充幣地址向出金地址進行轉賬交易。整個資金過程涉及大量的交易發送,流程很長且需要支付高額的 gas 費用。歷史上也出現過機構進行資金歸集導致鏈上交易費用攀升,交易擁堵的情況。
EIP-7702 的出現可以將 EOA 地址無縫轉化成合約錢包,由於 EIP-7702 的 gas 代付機制,不再需要 gas 充值交易的存在。同時可以利用合約錢包的可編程性,將多筆歸集轉賬打包在單筆交易中,減少交易數量並節約 gas 消耗。最終提高歸集效率,降低歸集成本。
EIP-7702 帶來的潛在風險
EIP-7702 帶來了新的賬戶功能,同時也引入了潛在的安全風險,需要錢包服務商、合約開發者、用戶保持警惕。
錢包服務商
由於 EIP-7702 引入了一個新的交易類型 SETCODETX_TYPE (0x04),也該交易類型也普通用戶直接相關。因此 Metamask, Rabby 等軟件錢包服務商與各種硬件錢包服務也需要更新軟件以適配新的交易類型。
由於 EIP-7702 授權存在接管整個賬戶的可能,因此需要錢包服務商在 UI 展示上給予用戶足夠的警示,提示級別應該與 Token Approve, Permit 相當甚至更高。
對新交易類型的對接、用戶交互上如果安全檢查不夠嚴格,有可能導致用戶遭受釣魚攻擊。
普通用戶
普通用戶也需要對以太坊新交易類型保持關注,留意各類軟件錢包及硬件錢包的更新。對新的特殊交易類型能夠有效的識別並投入足夠的重視。
此交易類型需要重點驗證 Delegation 的目標合約,在有技術儲備的前提下,最好能夠對合約源碼進行審計,避免引入安全風險。普通用戶則需要關注授權的合約是否開源並提供第三方可信的審計報告。
新交易類型相比以往的交易類型更難以審計,且具備更強的對錢包的控制能力。可以預見未來一定會出現使用此交易類型的釣魚攻擊。普通用戶一定要積極儲備相關的知識,提高安全意識。
合約開發者
對於合約開發者,EIP-7702 提供了新的視角。針對 Delegation 合約尚沒有成熟的公開庫組件或者開發標準,在升級的前期很可能需要開發者各自實現自己的 Delegation 合約。建議開發者進行足夠的調研,以保證規避新特性引入的安全風險。
經過 Cobo 安全團隊的分析,EIP-7702 在合約安全上需要注意的內容包括但不限於以下幾點:
1. Delegation 合約的初始化搶跑問題
EIP-7702 只提供了 set code 的能力,並不提供初始化合約的能力。對比開發者熟悉的 Proxy 機制來看,EIP-7702 相當於提供了更新 implemention 的能力,但未提供調用 initialize 函數的能力。
以現存的各種主流合約錢包為例,如 ERC-4337 官方實現中的錢包,其提供了 initialize 方法並且 initialize 方法上無任何權限檢查。第一個調用該方法的用戶可以獲取錢包的所有權。
contract SimpleAccount {
function initialize(address anOwner) public virtual initializer {
_initialize(anOwner);
}
}
包括 Safe 等其他主流合約錢包也基本都存在類似的問題。因為在過往合約錢包的實現中,往往將部屬合約和初始化打包在一個交易中,實現原子化操作,從而避免了搶跑問題的發生。
但在 EIP-7702 的場景下,授權簽名在 authorization_list 中單獨存在,搶跑機器人可以在內存池中監控授權交易,並搶先發送授權交易,同時調用初始化函數,搶奪合約錢包的權限。如果 EOA 錢包內已經有一定的加密資產,則可能在搶跑過程中直接進行資產轉移,給用戶造成資金損失。我們可以大膽推測在升級完成的最初一段時間,鏈上一定會出現基於 EIP-7702 初始化搶跑的攻擊發生。
經過調研,絕大部分原有 Proxy 模型下的代碼實現在 EIP-7702 場景下不能安全初始化。開發者應該對原有代碼進行 EIP-7702 適配後,再開放給用戶使用。用戶也應注意不要對各種舊版本合約進行授權,保證資金安全。
對於開發者來說,適配 EIP-7702 主要是對初始化方法進行權限校驗。典型的檢驗代碼可能形如:
require(msg.sender == address(this), "Only self")
或
require(ECDSA.recover(hash, signature) == address(this), "Only signed")
以保證只有 EOA 自身、或者持有合法簽名後才能調用初始化方法。考慮到 gas 代付場景,後者可能更為常用。
2. Delegation 合約的存儲結構衝突問題
在 EIP-7702 場景下,EOA 可能會頻繁的進行 Delegation 更新,相當於 Proxy 升級。由於各個 Delegation 合約可能由不同錢包廠商、DApp 開發者提供,彼此實現可能各不相同。不同於單一開發者場景下的合約升級那樣容易保證各個版本的兼容性。
不同 Delegation 合約的變量存儲結構大概率是完全不同的,如果合約間復用了相同的 Storage slot,那麼可能會讀取到錯誤的數據或者寫入非預期的數據,造成合約功能異常。並且數據一旦出錯,進行修復也需要很高的技術能力,普通用戶很難處理。
這裡推薦開發者使用 ERC-7201 的 Storage 管理模式,採用 Namespace 方式使用獨立的 Storage 空間,避免使用默認的 0x0 開始的 slot。
3. Delegation 權限管理問題
EIP-7702 與 Proxy 合約十分類似,但在 EIP-7702 場景下從以太坊協議級別進行了 implementation 合約的管理。相當於 Proxy 擁有一個固定不可變的 owner。因此 EOA 賬戶可隨時更新合約,修改 Storage 空間內的任意數據,進行任意操作。
開發者應該注意到這個不同,開發 DApp 時不能信任 EOA Storage 空間的數據,尤其是習慣了 Solana, SUI 用戶模型下的開發者更要注意這個問題。普通用戶在使用時也需要留意此問題。
比如將 EOA 代理到多簽錢包後,最高級的權限仍為 EOA 私鑰自身。
4. 新型 EOA 打破原有安全假設的問題
在舊版本合約中可能有些依賴發起者是 EOA 的安全假設會被打破。典型的,現有規範中常使用如下代碼檢查調用方是否為 EOA
require(msg.sender == tx.origin, "Only EOA")
進一步的可能假設 EOA 不具備合約調用能力而不進行批量調用的限制或者重入檢查邏輯。
在 EIP-7702 場景下,EOA 與 CA 邊界開始模糊,EOA 也具備執行代碼的能力。即使通過了上述檢查,向該 EOA 轉賬 ETH,仍可能觸發 EOA 代理合約的 fallback 導致重入問題。或者某些限制每個交易只能調用一次的方法(如某些代幣的挖礦分發方法、NFT mint 方法等),在新場景下可以通過 EOA Proxy 代碼實現批量調用,實現開發者非預期的套利攻擊。
參考資料
[1] EIP-3541: https://eips.ethereum.org/EIPS/eip-3541
[2] ERC-1167: https://eips.ethereum.org/EIPS/eip-1167
[3] EIP-7702: https://eips.ethereum.org/EIPS/eip-7702
[4] ERC-4337 SimpleAccount: https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/accounts/SimpleAccount.sol
[5] ERC-7201: https://eips.ethereum.org/EIPS/eip-7201