EIP-7702使簡單的以太坊錢包(EOAs)能夠升級爲智能合約錢包,提供更高的安全性、先進的功能、燃氣贊助機會以及其他好處。歷史上,智能錢包必須從頭開始創建,但隨着EIP-7702的引入,傳統錢包及其所有資產和鏈上歷史可以升級並保持相同的錢包地址。這就像從固定電話切換到智能手機,而無需更改號碼。
EOAs通過設置“委托指定”,即指向一個deleGate智能合約的指針,從而進行升級,其邏輯則管理EOA。因此,升級後的EOA可以擁有函數、設置存儲、發出事件,並執行智能合約可以做的所有其他操作。EOA可以隨時通過新的、籤名的EIP-7702授權更改或移除此委托。雖然這解鎖了許多新的可能性,但這一強大功能也引入了新穎的安全挑戰,需要謹慎考慮和創新解決方案。
爲了使EOAs能夠充當智能合約錢包,我們開發了EIP7702Proxy,一個輕量級的ERC-1967 代理合同旨在作爲 EIP-7702 deleGate 爲 EOA 服務。除了代理執行的基本邏輯轉發外,EIP7702Proxy 還包含解決多個 EIP-7702-deleGated 帳戶獨特挑戰的附加功能和設計選擇。設計 EIP7702Proxy 的目標是實現“標準部署”Coinbase 智能錢包與 EIP-7702-deleGated Coinbase 智能錢包之間盡可能接近的平價,這意味着將 EIP-7702 機制所需的額外復雜性抽象到專用代理中,並繼續依賴於 CoinbaseSmartWallet 的原始實現。這個挑戰的解決方案可以有效地應用於任何實現邏輯,而不僅僅是 CoinbaseSmartWallet 實現,同時幫助 EOA 在 7702 啓用的環境中保持安全。
我們在下面描述了具體的挑戰及相應的設計解決方案,這些解決方案使我們能夠安全地將任何現有的智能合約錢包實現調整爲用於EIP-7702升級。
實施EIP-7702的第一個主要障礙源於其初始化約束。傳統的智能合約錢包,包括CoinbaseSmartWallet,通常通過一個單獨的工廠合約在其部署期間以原子方式處理安全初始化(帳戶所有權的建立)。這種原子性意味着許多此類實現具有未受保護的初始化函數,這些函數只能被調用一次。然而,EIP-7702的設計不允許在代碼委托過程中執行初始化調用數據(與“部署”相當的步驟),因此無法以原子方式完成。
這種步驟的分離創建了一個關鍵的漏洞窗口。當通過EIP-7702將實現合約“部署”到EOA時,並不能保證該7702升級和初始化錢包的標準EVM交易將原子性地執行。設置授權的代碼在技術上可以獨立於初始化交易應用,即使它們同時提交,這可能允許攻擊者用自己的有效載荷前置初始化交易,並聲稱對智能帳戶的所有權。
注意,現有的Coinbase智能錢包是在一個後面部署的 ERC-1967 代理與一個UUPS可升級實現(實際的CoinbaseSmartWallet邏輯)。實際帳戶地址上的代碼是一個代理,代理使用ERC-1967定義的常規存儲位置來保存指向其實現邏輯的指針。我們在7702上下文中解決初始化漏洞的方法涉及到認識到任何實現邏輯只有在代理實際與其建立連接時才會變得活躍(因此危險)。因此,如果我們無法通過初始化強制執行原子部署,我們可以通過初始化來強制執行原子實現設置。
EIP-7702 CoinbaseSmartWallet 合約架構和邏輯委托流
在EIP-7702的背景下,EOA本身是對其帳戶任何變更的初始權威,必須提供籤名以授權初始化並確立新智能帳戶的任何所有者。我們的EIP7702Proxy合約實現了一個setImplementation函數,該函數可以原子性地設置新的邏輯實現並初始化帳戶。setImplementation函數:
驗證器是一個特定於實現的合約,包含邏輯以評估它是否認爲結果帳戶狀態是安全的。例如,在CoinbaseSmartWallet的情況下,CoinbaseSmartWalletValidator將檢查帳戶的所有權狀態是否非空,因此不再容易受到任意初始化的影響。
EIP-7702最復雜的挑戰或許與存儲管理有關。EOA可以隨時將其邏輯重新委托給不同的合約,或完全移除委托。所有委托共享EOA地址的同一存儲空間。多個合約在一段時間內共享對同一存儲的訪問可能會導致“存儲衝突”問題。存儲衝突發生在兩個合約對同一存儲位置進行不同的更改或假設時,這可能導致不可預測的錯誤。
存儲衝突的管理在代理設計領域已經是一個熟悉的問題,在這裏可變的實現邏輯用於管理共享存儲。盡管可升級的代理可以更改實現,但代理代碼本身(對於非7702地址)無法更改。這爲升級過程帶來了確定性和保證。7702重新委派爲可能控制此共享存儲的邏輯引入了另一個完全可變性的層次。這本質上消除了關於任意委派者對存儲可能產生影響的任何保證。例如,如果一個外部擁有帳戶(EOA)從委派者A委派到B再回到A,返回的委派者無法對其存儲的狀態做出假設,因爲該狀態可能已被委派者B擦除或操縱爲一個通過僅委派者A的邏輯無法實現的狀態。這對於任何7702委派者都是正確的,無論委派模式如何,因爲先前的委派者可能在任何存儲位置存儲或移除了任何內容.
DeleGate A 由於 A → B → A 委托模式導致的無效狀態示例
EOA委托可以任意影響帳戶狀態。如果一個EOA委托給一個惡意或破壞性的合約,任何現任的委托都無法對此提供保護。就像簽署一個排水交易,授權惡意的7702委托可能會導致災難,而防止這些結果超出了我們的設計範圍。
我們設計了EIP7702Proxy,使其能夠自我防御在一個多錢包、7702支持的生態系統中,面對那些出於好意但可能造成混亂的參與者所帶來的可預見問題。它無法保護那些授權真正惡意或存在缺陷的代理的外部擁有帳戶(EOA)。
一個可預見的問題涉及 setImplementation 調用的籤名以及可變帳戶狀態引入的風險。EIP7702Proxy 依賴於 EOA 籤名來設置實現邏輯並初始化到安全狀態。如果這些籤名變得可重放,它們可能會成爲負擔。例如,如果一個籤名授權了一個初始所有者,而這個所有者後來被攻破並移除,那麼一個可重放的籤名可能會重新建立被攻破的所有者或強制降級實現。
常見的防止籤名重放的保護措施是在籤名消息中使用隨機數,驗證後標記爲已使用。對於7702帳戶的風險是:其他代理可能會妥協這一隨機數跟蹤存儲。如果存儲跟蹤隨機數的使用被刪除,EOA的setImplementation籤名(在內存池中公開可用)在重新委托回EIP7702Proxy時可能會被重新應用。
爲了保證籤名的不重放性,我們實現了一個單例的 NonceTracker,它在帳戶存儲之外的不可變合約位置維護 nonce 狀態。只有 EOA 可以影響他們的 nonce(僅可遞增),防止其他委托者操縱這些安全關鍵值。NonceTracker 確保每個 setImplementation 籤名僅能使用一次,無論帳戶存儲如何變化。
標準化存儲槽,如同由 ERC-1967由於是傳統位置,可能被多個代理實現使用,因此特別容易受到潛在的存儲衝突。ERC-1967實現槽是EIP7702Proxy中唯一的標準存儲位置,它保存了代理所指向的邏輯實現的地址。我們的設計確保無論這個存儲位置的值是什麼(它決定了帳戶可用的大部分邏輯),EIP7702Proxy始終能夠成功將其實現邏輯設置爲EOA所需的合約。
爲了更清楚地說明所解決的問題,請注意,當一個帳戶在不同的代理(A→B→A)之間轉換時,如果這兩個代理都實現了ERC-1967代理模式,代理B自然會使用代理A用於存儲其實現地址的相同存儲槽。在其任期內,代理B可能會修改或覆蓋這個槽,無論是故意的還是作爲其自身代理操作的正常部分。在UUPSUpgradeable代理模式中,升級實現的邏輯是在實現合約本身上定義的。如果代理B在這個指針位置放置的實現不包含實現上預期的upgradeToAndCall接口,那麼當返回到代理A時,改變其實現的機制可能在當前可用邏輯中不存在。
示例:通過新的委托者覆蓋共享常規存儲位置
我們的EIP7702Proxy通過其setImplementation函數解決了這個問題,該函數提供了一種獨立於實現的升級機制,直接在代理本身上。這確保了即使一個中介deleGate將ERC-1967實現指向了一個無效的實現(或完全移除了它),原始的EOA在重新委托回EIP7702Proxy之後,仍然能夠重新配置代理的ERC-1967指針指向他們選擇的邏輯實現。
EIP7702Proxy的設計目標之一是保持與帳戶EOA功能的向後兼容性,此外還要支持新的智能合約功能。地址上代碼的存在與否會影響與該地址交互的協議的執行流程,因爲它們依賴於這一特性來區分EOA和智能合約。這就需要考慮兩種主要行爲:籤名驗證和代幣接收行爲。
智能合約的籤名驗證標準不同於標準的外部擁有帳戶(EOA)。智能合約實現了由定義的isValidSignature接口ERC-1271並且可以自由定義任意邏輯,以確定合同是否認爲籤名有效。對於標準的外部擁有帳戶(EOA),籤名通過標準的 ecrecover 檢查進行驗證,以確保籤名者恢復到預期的 EOA 地址。
爲了確保現有或未來的EOA籤名在7702升級後仍然能夠在EOA中得到承認,EIP7702Proxy實現了一個isValidSignature的版本,該版本首先將籤名驗證委托給應在邏輯實現中定義的isValidSignature函數,但在驗證失敗後進行最終的ecrecover檢查。如果檢查通過,則該籤名被視爲有效。通過這種方式,使用EIP7702Proxy的EOA可以保證,無論其智能合約錢包的isValidSignature實現如何,簡單的EOA籤名始終在其地址上得到承認。
一些代幣標準(具體來說,ERC-1155 和 ERC-721) 嘗試保護代幣不被困在可能沒有管理能力的智能合約中。這些代幣要求任何接收此類代幣的智能合約通過實現標準代幣接收者接口來聲明此能力,該接口在代幣合約進行代幣發送時被調用。升級後的外部擁有帳戶(EOA)中的邏輯還必須包含一個標準接收函數或可支付的回退,以能夠接收原生代幣。一個帳戶不應處於無法接收ETH或其他代幣的狀態,無論這種狀態持續多短時間。
由於我們的代理缺少初始實現,我們在缺少ERC-1967指針的情況下,將一個不可變的DefaultReceiver實現作爲EIP7702Proxy的默認邏輯。該接收器實現了接收函數和這些常見代幣標準的接收器鉤子,確保帳戶在明確設置新實現之前能夠接受代幣轉帳。
EIP7702Proxy設計使我們能夠與標準部署的CoinbaseSmartWallets保持緊密的一致性,並在解決EIP-7702背景下出現的獨特安全挑戰的同時,繼續使用現有的CoinbaseSmartWallet實現。通過仔細考慮初始化安全性、存儲不穩定性和幹擾的影響、對不間斷代幣處理的需求以及與標準EOA籤名驗證的向後兼容性,我們創建了一個用於安全委托和管理EIP-7702智能合約錢包的代理。雖然EIP7702Proxy是在考慮CoinbaseSmartWallet V1實現的情況下設計的,但該代理最終是與實現無關的。我們鼓勵開發者評估這一解決方案,以爲其他智能合約錢包實現進行7702-proofing。
EIP-7702使簡單的以太坊錢包(EOAs)能夠升級爲智能合約錢包,提供更高的安全性、先進的功能、燃氣贊助機會以及其他好處。歷史上,智能錢包必須從頭開始創建,但隨着EIP-7702的引入,傳統錢包及其所有資產和鏈上歷史可以升級並保持相同的錢包地址。這就像從固定電話切換到智能手機,而無需更改號碼。
EOAs通過設置“委托指定”,即指向一個deleGate智能合約的指針,從而進行升級,其邏輯則管理EOA。因此,升級後的EOA可以擁有函數、設置存儲、發出事件,並執行智能合約可以做的所有其他操作。EOA可以隨時通過新的、籤名的EIP-7702授權更改或移除此委托。雖然這解鎖了許多新的可能性,但這一強大功能也引入了新穎的安全挑戰,需要謹慎考慮和創新解決方案。
爲了使EOAs能夠充當智能合約錢包,我們開發了EIP7702Proxy,一個輕量級的ERC-1967 代理合同旨在作爲 EIP-7702 deleGate 爲 EOA 服務。除了代理執行的基本邏輯轉發外,EIP7702Proxy 還包含解決多個 EIP-7702-deleGated 帳戶獨特挑戰的附加功能和設計選擇。設計 EIP7702Proxy 的目標是實現“標準部署”Coinbase 智能錢包與 EIP-7702-deleGated Coinbase 智能錢包之間盡可能接近的平價,這意味着將 EIP-7702 機制所需的額外復雜性抽象到專用代理中,並繼續依賴於 CoinbaseSmartWallet 的原始實現。這個挑戰的解決方案可以有效地應用於任何實現邏輯,而不僅僅是 CoinbaseSmartWallet 實現,同時幫助 EOA 在 7702 啓用的環境中保持安全。
我們在下面描述了具體的挑戰及相應的設計解決方案,這些解決方案使我們能夠安全地將任何現有的智能合約錢包實現調整爲用於EIP-7702升級。
實施EIP-7702的第一個主要障礙源於其初始化約束。傳統的智能合約錢包,包括CoinbaseSmartWallet,通常通過一個單獨的工廠合約在其部署期間以原子方式處理安全初始化(帳戶所有權的建立)。這種原子性意味着許多此類實現具有未受保護的初始化函數,這些函數只能被調用一次。然而,EIP-7702的設計不允許在代碼委托過程中執行初始化調用數據(與“部署”相當的步驟),因此無法以原子方式完成。
這種步驟的分離創建了一個關鍵的漏洞窗口。當通過EIP-7702將實現合約“部署”到EOA時,並不能保證該7702升級和初始化錢包的標準EVM交易將原子性地執行。設置授權的代碼在技術上可以獨立於初始化交易應用,即使它們同時提交,這可能允許攻擊者用自己的有效載荷前置初始化交易,並聲稱對智能帳戶的所有權。
注意,現有的Coinbase智能錢包是在一個後面部署的 ERC-1967 代理與一個UUPS可升級實現(實際的CoinbaseSmartWallet邏輯)。實際帳戶地址上的代碼是一個代理,代理使用ERC-1967定義的常規存儲位置來保存指向其實現邏輯的指針。我們在7702上下文中解決初始化漏洞的方法涉及到認識到任何實現邏輯只有在代理實際與其建立連接時才會變得活躍(因此危險)。因此,如果我們無法通過初始化強制執行原子部署,我們可以通過初始化來強制執行原子實現設置。
EIP-7702 CoinbaseSmartWallet 合約架構和邏輯委托流
在EIP-7702的背景下,EOA本身是對其帳戶任何變更的初始權威,必須提供籤名以授權初始化並確立新智能帳戶的任何所有者。我們的EIP7702Proxy合約實現了一個setImplementation函數,該函數可以原子性地設置新的邏輯實現並初始化帳戶。setImplementation函數:
驗證器是一個特定於實現的合約,包含邏輯以評估它是否認爲結果帳戶狀態是安全的。例如,在CoinbaseSmartWallet的情況下,CoinbaseSmartWalletValidator將檢查帳戶的所有權狀態是否非空,因此不再容易受到任意初始化的影響。
EIP-7702最復雜的挑戰或許與存儲管理有關。EOA可以隨時將其邏輯重新委托給不同的合約,或完全移除委托。所有委托共享EOA地址的同一存儲空間。多個合約在一段時間內共享對同一存儲的訪問可能會導致“存儲衝突”問題。存儲衝突發生在兩個合約對同一存儲位置進行不同的更改或假設時,這可能導致不可預測的錯誤。
存儲衝突的管理在代理設計領域已經是一個熟悉的問題,在這裏可變的實現邏輯用於管理共享存儲。盡管可升級的代理可以更改實現,但代理代碼本身(對於非7702地址)無法更改。這爲升級過程帶來了確定性和保證。7702重新委派爲可能控制此共享存儲的邏輯引入了另一個完全可變性的層次。這本質上消除了關於任意委派者對存儲可能產生影響的任何保證。例如,如果一個外部擁有帳戶(EOA)從委派者A委派到B再回到A,返回的委派者無法對其存儲的狀態做出假設,因爲該狀態可能已被委派者B擦除或操縱爲一個通過僅委派者A的邏輯無法實現的狀態。這對於任何7702委派者都是正確的,無論委派模式如何,因爲先前的委派者可能在任何存儲位置存儲或移除了任何內容.
DeleGate A 由於 A → B → A 委托模式導致的無效狀態示例
EOA委托可以任意影響帳戶狀態。如果一個EOA委托給一個惡意或破壞性的合約,任何現任的委托都無法對此提供保護。就像簽署一個排水交易,授權惡意的7702委托可能會導致災難,而防止這些結果超出了我們的設計範圍。
我們設計了EIP7702Proxy,使其能夠自我防御在一個多錢包、7702支持的生態系統中,面對那些出於好意但可能造成混亂的參與者所帶來的可預見問題。它無法保護那些授權真正惡意或存在缺陷的代理的外部擁有帳戶(EOA)。
一個可預見的問題涉及 setImplementation 調用的籤名以及可變帳戶狀態引入的風險。EIP7702Proxy 依賴於 EOA 籤名來設置實現邏輯並初始化到安全狀態。如果這些籤名變得可重放,它們可能會成爲負擔。例如,如果一個籤名授權了一個初始所有者,而這個所有者後來被攻破並移除,那麼一個可重放的籤名可能會重新建立被攻破的所有者或強制降級實現。
常見的防止籤名重放的保護措施是在籤名消息中使用隨機數,驗證後標記爲已使用。對於7702帳戶的風險是:其他代理可能會妥協這一隨機數跟蹤存儲。如果存儲跟蹤隨機數的使用被刪除,EOA的setImplementation籤名(在內存池中公開可用)在重新委托回EIP7702Proxy時可能會被重新應用。
爲了保證籤名的不重放性,我們實現了一個單例的 NonceTracker,它在帳戶存儲之外的不可變合約位置維護 nonce 狀態。只有 EOA 可以影響他們的 nonce(僅可遞增),防止其他委托者操縱這些安全關鍵值。NonceTracker 確保每個 setImplementation 籤名僅能使用一次,無論帳戶存儲如何變化。
標準化存儲槽,如同由 ERC-1967由於是傳統位置,可能被多個代理實現使用,因此特別容易受到潛在的存儲衝突。ERC-1967實現槽是EIP7702Proxy中唯一的標準存儲位置,它保存了代理所指向的邏輯實現的地址。我們的設計確保無論這個存儲位置的值是什麼(它決定了帳戶可用的大部分邏輯),EIP7702Proxy始終能夠成功將其實現邏輯設置爲EOA所需的合約。
爲了更清楚地說明所解決的問題,請注意,當一個帳戶在不同的代理(A→B→A)之間轉換時,如果這兩個代理都實現了ERC-1967代理模式,代理B自然會使用代理A用於存儲其實現地址的相同存儲槽。在其任期內,代理B可能會修改或覆蓋這個槽,無論是故意的還是作爲其自身代理操作的正常部分。在UUPSUpgradeable代理模式中,升級實現的邏輯是在實現合約本身上定義的。如果代理B在這個指針位置放置的實現不包含實現上預期的upgradeToAndCall接口,那麼當返回到代理A時,改變其實現的機制可能在當前可用邏輯中不存在。
示例:通過新的委托者覆蓋共享常規存儲位置
我們的EIP7702Proxy通過其setImplementation函數解決了這個問題,該函數提供了一種獨立於實現的升級機制,直接在代理本身上。這確保了即使一個中介deleGate將ERC-1967實現指向了一個無效的實現(或完全移除了它),原始的EOA在重新委托回EIP7702Proxy之後,仍然能夠重新配置代理的ERC-1967指針指向他們選擇的邏輯實現。
EIP7702Proxy的設計目標之一是保持與帳戶EOA功能的向後兼容性,此外還要支持新的智能合約功能。地址上代碼的存在與否會影響與該地址交互的協議的執行流程,因爲它們依賴於這一特性來區分EOA和智能合約。這就需要考慮兩種主要行爲:籤名驗證和代幣接收行爲。
智能合約的籤名驗證標準不同於標準的外部擁有帳戶(EOA)。智能合約實現了由定義的isValidSignature接口ERC-1271並且可以自由定義任意邏輯,以確定合同是否認爲籤名有效。對於標準的外部擁有帳戶(EOA),籤名通過標準的 ecrecover 檢查進行驗證,以確保籤名者恢復到預期的 EOA 地址。
爲了確保現有或未來的EOA籤名在7702升級後仍然能夠在EOA中得到承認,EIP7702Proxy實現了一個isValidSignature的版本,該版本首先將籤名驗證委托給應在邏輯實現中定義的isValidSignature函數,但在驗證失敗後進行最終的ecrecover檢查。如果檢查通過,則該籤名被視爲有效。通過這種方式,使用EIP7702Proxy的EOA可以保證,無論其智能合約錢包的isValidSignature實現如何,簡單的EOA籤名始終在其地址上得到承認。
一些代幣標準(具體來說,ERC-1155 和 ERC-721) 嘗試保護代幣不被困在可能沒有管理能力的智能合約中。這些代幣要求任何接收此類代幣的智能合約通過實現標準代幣接收者接口來聲明此能力,該接口在代幣合約進行代幣發送時被調用。升級後的外部擁有帳戶(EOA)中的邏輯還必須包含一個標準接收函數或可支付的回退,以能夠接收原生代幣。一個帳戶不應處於無法接收ETH或其他代幣的狀態,無論這種狀態持續多短時間。
由於我們的代理缺少初始實現,我們在缺少ERC-1967指針的情況下,將一個不可變的DefaultReceiver實現作爲EIP7702Proxy的默認邏輯。該接收器實現了接收函數和這些常見代幣標準的接收器鉤子,確保帳戶在明確設置新實現之前能夠接受代幣轉帳。
EIP7702Proxy設計使我們能夠與標準部署的CoinbaseSmartWallets保持緊密的一致性,並在解決EIP-7702背景下出現的獨特安全挑戰的同時,繼續使用現有的CoinbaseSmartWallet實現。通過仔細考慮初始化安全性、存儲不穩定性和幹擾的影響、對不間斷代幣處理的需求以及與標準EOA籤名驗證的向後兼容性,我們創建了一個用於安全委托和管理EIP-7702智能合約錢包的代理。雖然EIP7702Proxy是在考慮CoinbaseSmartWallet V1實現的情況下設計的,但該代理最終是與實現無關的。我們鼓勵開發者評估這一解決方案,以爲其他智能合約錢包實現進行7702-proofing。