保障 EIP-7702 升级:一种安全实现 EOA 向智能钱包过渡的代理模式

中级6/19/2025, 8:25:18 AM
EIP-7702使传统钱包升级为智能合约钱包:技术解析、安全挑战及Coinbase的EIP7702Proxy提案

介绍

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升级。

挑战 #1:强制安全初始化

实施EIP-7702的第一个主要障碍源于其初始化约束。传统的智能合约钱包,包括CoinbaseSmartWallet,通常通过一个单独的工厂合约在其部署期间以原子方式处理安全初始化(账户所有权的建立)。这种原子性意味着许多此类实现具有未受保护的初始化函数,这些函数只能被调用一次。然而,EIP-7702的设计不允许在代码委托过程中执行初始化调用数据(与“部署”相当的步骤),因此无法以原子方式完成。

这种步骤的分离创建了一个关键的漏洞窗口。当通过EIP-7702将实现合约“部署”到EOA时,并不能保证该7702升级和初始化钱包的标准EVM交易将原子性地执行。设置授权的代码在技术上可以独立于初始化交易应用,即使它们同时提交,这可能允许攻击者用自己的有效载荷前置初始化交易,并声称对智能账户的所有权。

解决方案:要求EOA签名以原子方式设置实现并初始化

注意,现有的Coinbase智能钱包是在一个后面部署的 ERC-1967 代理与一个UUPS可升级实现(实际的CoinbaseSmartWallet逻辑)。实际账户地址上的代码是一个代理,代理使用ERC-1967定义的常规存储位置来保存指向其实现逻辑的指针。我们在7702上下文中解决初始化漏洞的方法涉及到认识到任何实现逻辑只有在代理实际与其建立连接时才会变得活跃(因此危险)。因此,如果我们无法通过初始化强制执行原子部署,我们可以通过初始化来强制执行原子实现设置。


EIP-7702 CoinbaseSmartWallet 合约架构和逻辑委托流

在EIP-7702的背景下,EOA本身是对其账户任何变更的初始权威,必须提供签名以授权初始化并确立新智能账户的任何所有者。我们的EIP7702Proxy合约实现了一个setImplementation函数,该函数可以原子性地设置新的逻辑实现并初始化账户。setImplementation函数:

  1. 验证来自EOA的签名,涉及关键数据,例如新实现合约的地址、初始化调用数据、将评估结果账户状态安全性的验证者合约地址,以及基本的签名重放保护措施,如随机数和过期时间。
  2. 将ERC-1967指针的值设置为新实现,并对新的逻辑实现执行提供的calldata
  3. 调用必须由签名中包含的验证器实现的validateAccountState函数。

验证器是一个特定于实现的合约,包含逻辑以评估它是否认为结果账户状态是安全的。例如,在CoinbaseSmartWallet的情况下,CoinbaseSmartWalletValidator将检查账户的所有权状态是否非空,因此不再容易受到任意初始化的影响。

挑战 #2:在 EIP-7702 代表之间共享存储

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 签名仅能使用一次,无论账户存储如何变化。

挑战 #3:共享传统存储位置的风险增加

标准化存储槽,如同由 ERC-1967由于是传统位置,可能被多个代理实现使用,因此特别容易受到潜在的存储冲突。ERC-1967实现槽是EIP7702Proxy中唯一的标准存储位置,它保存了代理所指向的逻辑实现的地址。我们的设计确保无论这个存储位置的值是什么(它决定了账户可用的大部分逻辑),EIP7702Proxy始终能够成功将其实现逻辑设置为EOA所需的合约。

为了更清楚地说明所解决的问题,请注意,当一个账户在不同的代理(A→B→A)之间转换时,如果这两个代理都实现了ERC-1967代理模式,代理B自然会使用代理A用于存储其实现地址的相同存储槽。在其任期内,代理B可能会修改或覆盖这个槽,无论是故意的还是作为其自身代理操作的正常部分。在UUPSUpgradeable代理模式中,升级实现的逻辑是在实现合约本身上定义的。如果代理B在这个指针位置放置的实现不包含实现上预期的upgradeToAndCall接口,那么当返回到代理A时,改变其实现的机制可能在当前可用逻辑中不存在。

示例:通过新的委托者覆盖共享常规存储位置

解决方案:可用的升级机制在EIP7702Proxy上

我们的EIP7702Proxy通过其setImplementation函数解决了这个问题,该函数提供了一种独立于实现的升级机制,直接在代理本身上。这确保了即使一个中介deleGate将ERC-1967实现指向了一个无效的实现(或完全移除了它),原始的EOA在重新委托回EIP7702Proxy之后,仍然能够重新配置代理的ERC-1967指针指向他们选择的逻辑实现。

挑战 #4:与标准 EOA 行为的向后兼容性

EIP7702Proxy的设计目标之一是保持与账户EOA功能的向后兼容性,此外还要支持新的智能合约功能。地址上代码的存在与否会影响与该地址交互的协议的执行流程,因为它们依赖于这一特性来区分EOA和智能合约。这就需要考虑两种主要行为:签名验证和代币接收行为。

签名验证

智能合约的签名验证标准不同于标准的外部拥有账户(EOA)。智能合约实现了由定义的isValidSignature接口ERC-1271并且可以自由定义任意逻辑,以确定合同是否认为签名有效。对于标准的外部拥有账户(EOA),签名通过标准的 ecrecover 检查进行验证,以确保签名者恢复到预期的 EOA 地址。

为了确保现有或未来的EOA签名在7702升级后仍然能够在EOA中得到承认,EIP7702Proxy实现了一个isValidSignature的版本,该版本首先将签名验证委托给应在逻辑实现中定义的isValidSignature函数,但在验证失败后进行最终的ecrecover检查。如果检查通过,则该签名被视为有效。通过这种方式,使用EIP7702Proxy的EOA可以保证,无论其智能合约钱包的isValidSignature实现如何,简单的EOA签名始终在其地址上得到承认。

代币收据

一些代币标准(具体来说,ERC-1155ERC-721) 尝试保护代币不被困在可能没有管理能力的智能合约中。这些代币要求任何接收此类代币的智能合约通过实现标准代币接收者接口来声明此能力,该接口在代币合约进行代币发送时被调用。升级后的外部拥有账户(EOA)中的逻辑还必须包含一个标准接收函数或可支付的回退,以能够接收原生代币。一个账户不应处于无法接收ETH或其他代币的状态,无论这种状态持续多短时间。

由于我们的代理缺少初始实现,我们在缺少ERC-1967指针的情况下,将一个不可变的DefaultReceiver实现作为EIP7702Proxy的默认逻辑。该接收器实现了接收函数和这些常见代币标准的接收器钩子,确保账户在明确设置新实现之前能够接受代币转账。

结论

EIP7702Proxy设计使我们能够与标准部署的CoinbaseSmartWallets保持紧密的一致性,并在解决EIP-7702背景下出现的独特安全挑战的同时,继续使用现有的CoinbaseSmartWallet实现。通过仔细考虑初始化安全性、存储不稳定性和干扰的影响、对不间断代币处理的需求以及与标准EOA签名验证的向后兼容性,我们创建了一个用于安全委托和管理EIP-7702智能合约钱包的代理。虽然EIP7702Proxy是在考虑CoinbaseSmartWallet V1实现的情况下设计的,但该代理最终是与实现无关的。我们鼓励开发者评估这一解决方案,以为其他智能合约钱包实现进行7702-proofing。

免责声明:

  1. 本文转载自 [基础工程博客]. 所有版权归原作者所有 [Amie Corso]. 如果对此转载有异议,请联系 Gate Learn团队,他们会及时处理。
  2. 责任免责声明:本文中表达的观点和意见仅代表作者个人,并不构成任何投资建议。
  3. 文章的翻译由 Gate Learn 团队完成。除非另有说明,禁止复制、分发或剽窃翻译后的文章。

保障 EIP-7702 升级:一种安全实现 EOA 向智能钱包过渡的代理模式

中级6/19/2025, 8:25:18 AM
EIP-7702使传统钱包升级为智能合约钱包:技术解析、安全挑战及Coinbase的EIP7702Proxy提案

介绍

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升级。

挑战 #1:强制安全初始化

实施EIP-7702的第一个主要障碍源于其初始化约束。传统的智能合约钱包,包括CoinbaseSmartWallet,通常通过一个单独的工厂合约在其部署期间以原子方式处理安全初始化(账户所有权的建立)。这种原子性意味着许多此类实现具有未受保护的初始化函数,这些函数只能被调用一次。然而,EIP-7702的设计不允许在代码委托过程中执行初始化调用数据(与“部署”相当的步骤),因此无法以原子方式完成。

这种步骤的分离创建了一个关键的漏洞窗口。当通过EIP-7702将实现合约“部署”到EOA时,并不能保证该7702升级和初始化钱包的标准EVM交易将原子性地执行。设置授权的代码在技术上可以独立于初始化交易应用,即使它们同时提交,这可能允许攻击者用自己的有效载荷前置初始化交易,并声称对智能账户的所有权。

解决方案:要求EOA签名以原子方式设置实现并初始化

注意,现有的Coinbase智能钱包是在一个后面部署的 ERC-1967 代理与一个UUPS可升级实现(实际的CoinbaseSmartWallet逻辑)。实际账户地址上的代码是一个代理,代理使用ERC-1967定义的常规存储位置来保存指向其实现逻辑的指针。我们在7702上下文中解决初始化漏洞的方法涉及到认识到任何实现逻辑只有在代理实际与其建立连接时才会变得活跃(因此危险)。因此,如果我们无法通过初始化强制执行原子部署,我们可以通过初始化来强制执行原子实现设置。


EIP-7702 CoinbaseSmartWallet 合约架构和逻辑委托流

在EIP-7702的背景下,EOA本身是对其账户任何变更的初始权威,必须提供签名以授权初始化并确立新智能账户的任何所有者。我们的EIP7702Proxy合约实现了一个setImplementation函数,该函数可以原子性地设置新的逻辑实现并初始化账户。setImplementation函数:

  1. 验证来自EOA的签名,涉及关键数据,例如新实现合约的地址、初始化调用数据、将评估结果账户状态安全性的验证者合约地址,以及基本的签名重放保护措施,如随机数和过期时间。
  2. 将ERC-1967指针的值设置为新实现,并对新的逻辑实现执行提供的calldata
  3. 调用必须由签名中包含的验证器实现的validateAccountState函数。

验证器是一个特定于实现的合约,包含逻辑以评估它是否认为结果账户状态是安全的。例如,在CoinbaseSmartWallet的情况下,CoinbaseSmartWalletValidator将检查账户的所有权状态是否非空,因此不再容易受到任意初始化的影响。

挑战 #2:在 EIP-7702 代表之间共享存储

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 签名仅能使用一次,无论账户存储如何变化。

挑战 #3:共享传统存储位置的风险增加

标准化存储槽,如同由 ERC-1967由于是传统位置,可能被多个代理实现使用,因此特别容易受到潜在的存储冲突。ERC-1967实现槽是EIP7702Proxy中唯一的标准存储位置,它保存了代理所指向的逻辑实现的地址。我们的设计确保无论这个存储位置的值是什么(它决定了账户可用的大部分逻辑),EIP7702Proxy始终能够成功将其实现逻辑设置为EOA所需的合约。

为了更清楚地说明所解决的问题,请注意,当一个账户在不同的代理(A→B→A)之间转换时,如果这两个代理都实现了ERC-1967代理模式,代理B自然会使用代理A用于存储其实现地址的相同存储槽。在其任期内,代理B可能会修改或覆盖这个槽,无论是故意的还是作为其自身代理操作的正常部分。在UUPSUpgradeable代理模式中,升级实现的逻辑是在实现合约本身上定义的。如果代理B在这个指针位置放置的实现不包含实现上预期的upgradeToAndCall接口,那么当返回到代理A时,改变其实现的机制可能在当前可用逻辑中不存在。

示例:通过新的委托者覆盖共享常规存储位置

解决方案:可用的升级机制在EIP7702Proxy上

我们的EIP7702Proxy通过其setImplementation函数解决了这个问题,该函数提供了一种独立于实现的升级机制,直接在代理本身上。这确保了即使一个中介deleGate将ERC-1967实现指向了一个无效的实现(或完全移除了它),原始的EOA在重新委托回EIP7702Proxy之后,仍然能够重新配置代理的ERC-1967指针指向他们选择的逻辑实现。

挑战 #4:与标准 EOA 行为的向后兼容性

EIP7702Proxy的设计目标之一是保持与账户EOA功能的向后兼容性,此外还要支持新的智能合约功能。地址上代码的存在与否会影响与该地址交互的协议的执行流程,因为它们依赖于这一特性来区分EOA和智能合约。这就需要考虑两种主要行为:签名验证和代币接收行为。

签名验证

智能合约的签名验证标准不同于标准的外部拥有账户(EOA)。智能合约实现了由定义的isValidSignature接口ERC-1271并且可以自由定义任意逻辑,以确定合同是否认为签名有效。对于标准的外部拥有账户(EOA),签名通过标准的 ecrecover 检查进行验证,以确保签名者恢复到预期的 EOA 地址。

为了确保现有或未来的EOA签名在7702升级后仍然能够在EOA中得到承认,EIP7702Proxy实现了一个isValidSignature的版本,该版本首先将签名验证委托给应在逻辑实现中定义的isValidSignature函数,但在验证失败后进行最终的ecrecover检查。如果检查通过,则该签名被视为有效。通过这种方式,使用EIP7702Proxy的EOA可以保证,无论其智能合约钱包的isValidSignature实现如何,简单的EOA签名始终在其地址上得到承认。

代币收据

一些代币标准(具体来说,ERC-1155ERC-721) 尝试保护代币不被困在可能没有管理能力的智能合约中。这些代币要求任何接收此类代币的智能合约通过实现标准代币接收者接口来声明此能力,该接口在代币合约进行代币发送时被调用。升级后的外部拥有账户(EOA)中的逻辑还必须包含一个标准接收函数或可支付的回退,以能够接收原生代币。一个账户不应处于无法接收ETH或其他代币的状态,无论这种状态持续多短时间。

由于我们的代理缺少初始实现,我们在缺少ERC-1967指针的情况下,将一个不可变的DefaultReceiver实现作为EIP7702Proxy的默认逻辑。该接收器实现了接收函数和这些常见代币标准的接收器钩子,确保账户在明确设置新实现之前能够接受代币转账。

结论

EIP7702Proxy设计使我们能够与标准部署的CoinbaseSmartWallets保持紧密的一致性,并在解决EIP-7702背景下出现的独特安全挑战的同时,继续使用现有的CoinbaseSmartWallet实现。通过仔细考虑初始化安全性、存储不稳定性和干扰的影响、对不间断代币处理的需求以及与标准EOA签名验证的向后兼容性,我们创建了一个用于安全委托和管理EIP-7702智能合约钱包的代理。虽然EIP7702Proxy是在考虑CoinbaseSmartWallet V1实现的情况下设计的,但该代理最终是与实现无关的。我们鼓励开发者评估这一解决方案,以为其他智能合约钱包实现进行7702-proofing。

免责声明:

  1. 本文转载自 [基础工程博客]. 所有版权归原作者所有 [Amie Corso]. 如果对此转载有异议,请联系 Gate Learn团队,他们会及时处理。
  2. 责任免责声明:本文中表达的观点和意见仅代表作者个人,并不构成任何投资建议。
  3. 文章的翻译由 Gate Learn 团队完成。除非另有说明,禁止复制、分发或剽窃翻译后的文章。
即刻开始交易
注册并交易即可获得
$100
和价值
$5500
理财体验金奖励!