本文探讨了以太坊账户抽象的迁移方案,主要集中于外部拥有账户(EOA)向智能合约账户的转换,以及相关的以太坊改进提议(EIP-5003、EIP-7377、EIP-7702)。文章分析了这种迁移的必要性、潜在利益和局限性,同时讨论了合约账户的灵活性与EOA的自主性之间的权衡。结论表明,虽然迁移方案在短期内提供了兼容性,但并不足以实现全面的账户抽象。未来的工作将专注于原生账户抽象的解决方案。
这段关于账户抽象的系列文章的第一部分建立了一个全面的框架,以思考账户抽象的问题。具体来说,它评估了一些选定的EIP,展示了可编程EOA的能力。
EOA的可编程性运动得益于原生智能账户(native smart accounts)的(相对)缓慢发展,以及唯一现有的非协议账户抽象系统ERC-4337对EOA缺乏支持(尽管ERC-4337从来不打算为EOA服务)。
这一系列的第二篇文章涵盖了实现账户抽象的另一种方法:将EOA(外部拥有账户)转换为合同账户(又称:EOA迁移)。这一发展路径在某种程度上与最初的目标一致,即让每个用户主要使用智能合约钱包操作合同账户。
本文讨论的方案提出了将账户自愿从EOA转换为合同账户的方法。虽然所覆盖的提案没有被积极追求,但仍有必要从历史背景上进行讨论。
让我们深入探讨。
在之前,我们讨论了EOA(外部拥有账户)和合同账户之间的差异。特别是我们认为,这归结于用户在自主权和可编程性之间的偏好。
EOA由私钥控制,并承诺提供较高的自主权:用户可以始终生成和管理一个EOA,而无需依赖第三方。然而,对私钥的依赖限制了EOA的可编程性。
例如,EOA无法拥有替代方案(例如,多方签名)来验证交易。为什么?以太坊协议只将用私钥生成的ECDSA(椭圆曲线数字签名算法)签名视为验证账户拥有者批准交易的唯一方式。
合同账户由其地址上部署的代码控制,并支持更为可编程的规则来验证和执行交易。例如,一个合同账户可以使用多方签名(交易需要由多个账户签名才能有效)。
在这里,验证者不一定关心签名是否由私钥生成(合同账户反正没有私钥)。更重要的是验证交易是否符合合同代码中规定的有效性要求。
合同账户比EOA更灵活和可编程,但给予用户的控制权较少。例如,一个合同账户不能主动发起交易,而需要一个EOA发送交易以触发已部署在前者地址上的代码执行。
这与之前的说法并不矛盾,即合同账户可以支持任意授权方案?并不完全是。以太坊尚未将智能合约视为“第一类”公民,而是将EOA使用的ECDSA签名视为验证所有交易的默认方式。
我们可以通过使用Alice的例子来探讨这对合同账户意味着什么。她拥有一个使用2-of-2多重签名方案来批准交易的合同账户。一个以太坊节点无法确认账户的所有者是否已授权该交易,因为它只期望由私钥生成单一签名,而不是同一交易上的两个签名。
EOA必须发送一笔“调用”智能合约的交易,触发Alice排队的操作的执行。如果EOA的签名通过验证,剩下的唯一任务便是确认该操作遵从于合同代码中编程的有效性规则。这意味着要进行如下操作:
请注意,除非她有一个EOA,Alice无法与她的合同账户互动——但这会使创建合同账户的意义失去。因此,她可以依靠某个第三方来帮助传递交易,但这使她面临审查的风险,如果第三方拒绝她的请求。
然而,如果Alice拥有一个能够自主发送交易的EOA,体验将会有所不同。审查只能在协议层发生(以太坊验证者拒绝将她的交易包含到区块中)——并且存在潜在的对抗此类审查的防御机制。
这一微型探讨揭示了EOA和合同账户之间的差异,捕捉了我们所描述的“以太坊账户困境”。用户希望账户能够完全可编程,但也希望保持自主权,并受益于EOA提供的审查抵抗力。
此时,一个问题浮现:“我们难道不能仅通过允许智能合约授权交易或允许EOA像智能合约一样工作来解决这个问题吗?”这一系列中的各种提案旨在升级智能合约账户或升级EOA,以使账户抽象成为可行。
本报告考虑了一组提案(EIP-7702(通过CODERESET)、EIP-5003 和 EIP-7377),旨在将EOA转换为合同账户。采取这种方法的一大好处是用户无需部署新的(智能合约)账户来利用AA功能。我们可以简单地升级现有的EOA,以执行代码并实施可编程的交易授权和访问策略。
在深入探讨EOA迁移标准之前,我们将简要介绍EIP-3607——这一标准为许多提案奠定了基础,使EOA能够转换为合同账户。EIP-3607对于安全地让用户能够将其EOA迁移到合同账户至关重要,这是接下来的章节的重点。
EIP-3607通过规定以太坊协议必须始终拒绝指定为tx.origin的包含代码的账户交易,定义了合同账户的自主权缺失。这是为了防止前地址冲突可能产生的问题,即一个单一生成的地址可以由代码内容和私钥共同控制。
其基本推理很简单:由于以太坊地址的160位长度,可以生成一个合同账户和一个EOA,其地址具有相同的值(即它们的地址发生冲突)。这已计算,假设一年内的运行成本为100亿美元,生成260至180个算法操作是可行的。
这种地址冲突的潜在滥用之一是,恶意行为者可能会通过伪装成合同并保持一个私钥来利用用户。这可能会被不诚实的一方用来部署一个合同账户——其访问政策被EOA的私钥所超越——以吸引用户的资金,并在之后偷走它们。
虽然由两个具有相同地址的账户生成的此类攻击向量由于生成两个账户的成本而显得相当不可行,但为了安全起见,将其彻底禁止是更为合适的。EIP-3607实现了这一目标。
上一篇文章讨论了tx.origin
和msg.sender
之间的差异:tx.origin
授权一笔交易,而msg.sender
“承载”一笔交易。EIP-3607明确禁止合同账户作为tx.origin存在——也就是说,它们不能用于授权任何交易。对于任何tx.origin
的非空代码哈希值的交易,协议必须将其拒绝为无效。
探讨完EIP-3607后,我们将继续探索其他旨在将EOA转换为合同账户的EIP(以太坊改进提案),并展示它们与EIP-3607(以及其他内容)的相互关系。
一般来说,EOA迁移在早期几乎没有被考虑,因为它暴露了许多问题。尽管如此,它为实现账户抽象的一些目标提供了一条(棘手的)路线。
EOA迁移涉及通过分配一个非零代码值并撤销其私钥来将EOA转换为合同账户。这种代码值分配可以通过允许EOA直接复制现有合同的代码来完成,或者通过允许其“指向”现有合同的代码——基本上是将其执行逻辑委托给合同。
该类别中提出的两个主要EIP是EIP-5003和EIP-7377。EIP-5003预计将补充EIP-3074,而EIP-7377是一个独立的EOA迁移提案。EIP-7702允许用户使用CODERESET操作码在EOA和合同账户之间迁移。
接下来的章节将讨论这些提案的规范。我们还将比较和对比EOA迁移提案——重点关注它们的实现细节、关键特征和限制。
EIP-5003被引入作为对EIP-3074的补充,以允许符合EIP-3074的EOA撤销其原始ECDSA格式的签名。正如在之前的报告中讨论的那样,EIP-3074允许“签名抽象”或“授权抽象”,并允许EOA使用[AUTH]
和[AUTHCALL]
操作码定义新型交易授权政策。然而,它不允许撤销EOA的原始私钥。
EIP-3074的AUTH
操作码导致authority
账户(EOA的所有者)将tx.origin
函数偏移到authorized
账户(被授权代表EOA发送交易的“调用者”),同时保持msg.sender
。EIP-5003的AUTHUSURP
扩展了该过程,允许authority
完全撤销使用账户的私钥授权交易的能力。
EIP-5003的道理很简单:虽然EIP-3074允许EOA表现得像合同账户,但私钥的存在是一个限制因素——特别是因为私钥是一个单点故障。智能合同账户通过实施新型签名方案(例如多重签名)解决了这个问题,但在启用了EIP3074的EOA中,不能利用这一点,因为原始私钥仍然拥有签署交易的权力。
EIP-5003允许用户自愿废弃账户的私钥,完成EOA与合同账户的转换。EIP-5003迁移完成后,用户将无法再使用私钥签署交易——所有交易现在根据合同账户逻辑中定义的规则得以验证。
该EIP提议添加操作码AUTHUSURP
,其作用是在原始EOA地址处部署一个智能合约。这有效地撤销了私钥的授权权力,因为EIP-3607阻止包含代码的地址像EOA一样进行签署交易。
AUTHUSURP
所提供的功能类似于[CREATE
操作码,但进行了几次调整:
authorized
字段将使AUTHUSURP
的操作无效。AUTHUSURP
不会检查authorized
账户的nonce。AUTHUSURP
的initcode在authorized
账户的上下文中运行,并且必须返回非零字节值。AUTHUSURP
的initcode执行后返回的代码会部署到authorized
账户中。总之:EIP-5003提议新增操作码AUTHUSURP
,该操作码有效地导致[authorized]
账户的内容代码在目标地址(通常为authority
)的账户处进行部署,从而使其私钥失效。当与EIP-3074配合使用时,EIP-5003允许EOA完全迁移到合同账户。
围绕EIP-5003机制的一个主要关切是它暴露于通过许可系统的攻击向量。为了理解这一点,我们不得不退后一步重新了解ecRecover预编译是什么。
ecRecover预编译是一个负责促进数字签名安全高效验证的系统合约。这使得ecRecover预编译与每个EOA的身份验证逻辑密切相关。
当用户对消息进行签名时,生成的签名与签名消息一起呈现。调用ecRecover合约时通过消息的哈希值与签名,允许以太坊节点从签名中恢复EOA的公钥。这样,任何人都可以验证该签名确实属于特定账户。
从技术上讲,当一个EOA使用其基于ECDSA的私钥签署交易时,输出是一个哈希消息(交易哈希),以及由三个值组成的签名:恢复识别符“v
”、x值“r
”和“s
”。
然后ecRecover合约使用这些值推断出对应的公共地址。这被用作证明消息确实是从对应账户发出的。
此过程在以太坊中有着许多用例,可以大致分为:
这对EIP-5003有严重的影响,特别是在像permit2这样的方案中,允许授权dapp访问用户所拥有的ERC-20代币。一旦这种权限被授权,它将在预定义的截止日期之前有效——除非用户手动在之前撤销相关代币合约的权限。
许多DeFi协议依赖于类似permit的授权来执行涉及访问代币的操作,而无需用户每次手动授予许可。例如,“收益优化器”旨在通过在各种DeFi协议中存入资产以赚取利息(例如向Uniswap池提供流动性以赚取流动性提供者(LP)份额),并需要授权以代表用户移动代币。
也就是说,permit
对选择EIP-5003的用户存在问题。通常情况下,EIP-5003撤销用户的私钥并阻止其签署交易。但ecRecover会在未检查代码的情况下恢复原始签名——这意味着我们可能会遇到私钥仍能授权交易并支出账户资金的情景。
因此,EIP-5003的风险在于,恶意行为者可以利用访问撤销的私钥来访问账户资金,即使用户已经实施了替代的交易授权方案。此外,账户还面临异国跨链攻击方案的风险,其中原始签名可以在不同的与以太坊虚拟机兼容的链上访问该账户的资金,这些链使用相同的密钥对。
也有论点提议调整ecRecover预编译合约的行为以防止上述与权限有关的问题。然而,它已经成为一个存在了很久的加密原语,任何形式上的更改几乎肯定会导致在运行合同中出现问题,从而造成一种难以解决的困境。
虽然EIP-5003旨在与已经实现EIP-3074的账户一起工作,但EIP-7377将两个提案的功能打包到一个单一的交易包中。因此,发送EIP-7377交易将导致一个EOA直接获取代码值——隐式地撤销/禁用私钥——并获得访问可编程授权策略的能力。
EIP-7377提议引入一种新的EIP2718兼容交易类型,其格式为:
[0x04 || rlp([chainID, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, codeAddr, storage, data, value, access_list, signature_y_parity, signature_r, signature_s])].
其中:codeAddr
是将被复制代码值的账户地址。它的实现方式是,只要该地址已经部署了代码,这个函数的任何地址都是有效的(请参考第一篇报告,我们讨论其他变量的行为)。
签署此交易将允许用户在EOA的地址上部署他们所选择的任何可执行代码。这将EOA变为合同账户并使原始私钥失效。与EIP-5003一样,此功能依赖于EIP-3607。
此负载的执行分为两个阶段:
keccak255(sender)[0 … 20]
。这有两个目的:
EIP-7377被设计为使用代码指针,而不是导致一个账户承担实际的代码值。也就是说,源账户承担其私钥的签名权威降级的逻辑,并在用户希望在他们账户中实现其功能的智能合约代码中放置一个指针。这便于使用,因为用户希望为EOA实施的大部分功能通常已经存在。
在设置完代码指针后,账户将立即调用所指定的[data]和[value]变量,以验证迁移过程是否成功。该过程旨在是原子的,因此,如果调用失败,账户将保持为普通EOA。
EIP-7377交易还不包含“to”值,因为它对于每个账户仅有效一次(“一旦是合约,始终是合约”,根据EIP-3607的说法)。来自已经执行负载的账户的后续交易,导致代码值提供依赖其逻辑的附加功能。这使其在所有意图上都成为合同账户,并消除了授权交易的能力。
codeAddr
值的灵活性在本提案中呈现出双刃剑的特性。尽管交易的高自定义性允许任何包含已部署和可执行EVM代码的地址作为codeAddr
值,但同样的灵活性引入了显著的安全风险。
例如,毫无警觉的用户可能会授权他们的EOA指向具有能力窃取资产或执行恶意逻辑的恶意合约。由于用户通常签署代码而无法阅读或验证此codeAddr
值,这种风险加大。
一种潜在的缓解策略反映了对EIP-3074调用者合约的提议,其中钱包提供商将可签署的合约限制为经过验证的可信代理。但该规范仍缺乏一个明确的解决方案,以平衡无许可创新(使用多个调用者)与安全忧虑(避免恶意调用者)。
EIP-7377的Gas定价机制通过合同迁移成本的折扣创造了全局性的脆弱性,该成本是不依赖于部署代码大小来计算的。该折扣在合同部署阶段提出(设置代码所消耗的存储槽)。
智能合约开发者可能通过设置EOA、向其积累资金,然后使用EIP-7377交易进行迁移而获利。问题在于,这种初始化方式的合约将在交易的第一阶段中任意分配存储槽,导致槽与映射不具相关性,最终导致合约的存储分配不透明。
上述复杂性可能导致一种情况,即已部署的代币合约在任意地址上持有代币余额,而除了合约创建者之外没有其他人知道这个情况。另一个相关的例子是,以这种方式创建的多签名合约并未立即使其签名者显而易见。只有合约创建者知道,而在链上没有办法验证。
在优化和其他OP-Stack L2中,想要进行存款的L1合约将其地址转换为L2上的等效别名,使用代码:
// 如果调用者是合同,则将from-address转换为其别名 address from = msg.sender; if (msg.sender != tx.origin) { from = AddressAliasHelper.applyL1ToL2Alias(msg.sender); }
这种逻辑是必要的,以便L2能够辨别在L1和L2上地址碰撞而具有不同逻辑(或控制者)的账户。然而,由于假设它们是由同一个实体控制,因此不适用于EOA。
这种设计还防止由于使用的调用方法导致地址多重性而引起的混乱。目前,L2合约可以通过来自L1的直接存款交易,或者通过L2的序列交易进行调用。
然而,EIP-7377允许一个EOA迁移到合同账户,因此在相关OP L2上失去其别名豁免。因此,该EOA将失去发送直接存款交易的能力,可能会因无法强制包含交易而减少L2的审查抵抗能力。
EIP-7377同样面临与EIP-5003相同的问题,即与权限系统有关的。使用权限系统进行授权/身份验证的应用将在无法进行交易的情况下遇到问题,但ecRecover仍会恢复ECDSA签名。因此,如果在EIP实现后,验证签名的智能合约未检查代码,将对用户构成很大风险。
EIP-7702中引入的变化在以太坊中建立了一种新的账户标准——迁移的EOA,除了两种传统标准(合同账户和EOA)之外。这些迁移的EOA可以表现得像EOA(使用其私钥授权发送交易),同时具有执行其指向的代码的附加能力(因此表现为合同账户)。
在当前的规范中,这些迁移的EOA的私钥是一个有效的访问策略,具有更大于其包含代码的权力。这使得提案可能面临与我们之前讨论的EIP-3074类似的问题,其中私钥泄漏仍可能对用户造成损害。
CODERESET
一词用于指一系列提议的变化,使得EIP-7702与EIP-3607兼容,使得实施EIP-7702的EOA有效地成为合同账户,无法使用私钥支出资金。同时,用户还可以通过使用CODERESET
操作码来将迁移后的EOA恢复为普通EOA,删除其代码。
如此处解释的那样,EIP-7702当前的规范仅支持持久的合同账户——这意味着账户不能在任何一个标准间反弹。此外,迁移的EOA可以将其私钥作为有效的访问策略保留,同时使其包含的代码在其他场景中能够使用。
因此,该账户能够通过原始私钥绕过其涵盖代码中编码的所有链上策略。这使得该账户无法实施类似多重签名和时间锁这样的替代交易授权策略以提高安全性。
从技术上讲,该账户可以实施这些策略,但并不重要,因为私钥总是可以覆盖它们。因此,它并不像通常没有“主密钥”的情况下那样安全。
这一模型允许迁移的EOA在具有协议限制的情况下表现得如同“普通EOA”,而且通常表现为合同账户,从而使其安全性保障变得复杂,因为没有对协议的操作池(mempool)进行补充变更以适应此类账户。
为了提供背景,每个账户类型具有不同的约束:
EIP-7702的迁移的EOA目前设置为由本地操作池处理其交易,其逻辑不针对能够同时作为EOA和合同账户的账户进行优化。因此,这一账户标准可能会引入新的Sybil攻击向量。
通过将CODERESET
操作码添加到EIP-7702所建议的变化的核心内容如下:
tx.origin
使用,从而使其符合EIP-3607,无法通过私钥为事务提供授权。CODERESET
操作码时重置为普通的EOA,该操作码删除其代码。此外,增设一个可选的calldata
字段以允许用户在其迁移过程中明确定义账户的存储变量。这一特性确保账户的设置和代码部署原子性地执行,以防快速前导攻击(frontrunning attacks)中,恶意行为者可能将目标内容代码的地址替换为不同的值并控制账户。
本提案引入的变化提供了多项显著好处。首先,它们维持了Sybil抵抗机制的持久性。EOA和合同账户在行为上通常具有明确规定的限制,通常通过链内约束或其内容代码实现。当EOA能够伪装成合同账户时,引入的新的安全考量让当前的操作池设计没有准备好应对。通过限制EIP-7702账户的行为要么为EOA,要么为合同账户,该提案维持了现有的安全假设。
另一个关键优势是政策的持久性。由于私钥不再是EIP-7702账户的有效访问策略,开发者可以实施更复杂的访问策略,例如多重签名和时间锁,降低复杂性和开销。这一简化使其更为实际可行。
该提案还提供了另一个引人注目的功能:账户在执行期间能够接受临时功能。通过在EIP-7702中包含CODERESET
操作码,通过在初始化交易中传递的calldata可以在完成目标内容代码逻辑后执行该操作码——整个过程以原子方式进行。这使得EOA能以自身身份启动交易,在执行过程中转变为合同账户,并在完成后回归EOA状态。
该提案在其安全模型方面面临重大批评。特别是与ecRecover相关的权限系统的不兼容性令人担忧。
使用ecRecover预编译的应用程序如果不支持ERC-1271,将无法正确验证迁移的EOA的特权,因为该预编译在没有检查签名者代码的情况下恢复公地址。这使迁移的EOA在其密钥遭到泄露时容易遭受到资产损失,特别是在缺乏ERC-1271的验证的应用中。
恢复机制引入了进一步的安全风险(尽管将迁移的EOA的私钥保持为有效访问策略创建了一个链内撤销路径)。恶意或意外行为可能覆盖授权,要么通过重新授权到不同合约,要么通过通过零地址或EOA的地址回复至普通EOA状态。
然而,第一个点可能无关紧要,因为大多数能够通过权限系统支出的资产都支持ERC-1271。至于第二个点,我们可以辩论私钥泄露是否在将私钥存在作为账户逻辑的主密钥面对所有资产的支出访问权时更具害处——相较于仅拥有支出支持ecRecover权限的代币的情况下。因此,这主要是一个关于复杂主题的消费者教育问题。
尽管对新[CODERESET]操作码提出的变化被视为过于复杂,但其优势相当可观,导致对重新授权方案和更高级别访问策略的讨论。关于EIP-7702的规范仍存在许多争议,但迁移账户清除授权的唯一方法是重新授权到一个空账户。
我们认为,通往原生账户抽象的可行途径的一项目标是必须在以太坊生态系统中保持可组成性。从EOA转换为合同账户的最明显的缺点是,这一方法没有满足此条件,原因在于其固有的状态漂移问题。
当一个EOA在一个链上撤销其私钥访问时,例如使用EIP-7377,它必须在所有该地址存在的链上复制此操作。如果没有普遍的迁移,该账户将依然容易受到私钥攻击,而在尚未进行迁移的链上。
EIP-7377和EIP-5003在今天的以太坊上面临着重大的采纳挑战,因为它们将需要在整个以太坊L1/L2生态系统内实施。在每一条链上完成密钥撤销的需要给用户增加了太多的复杂性,使得这种提案变得不具吸引力。
另一个一般论点是反对将EOA迁移至合同标准,认为这是某种循环发展。因为目前的共识是两者在各自的方式下都有缺陷,所以我们应尝试解决它们观察到的缺陷,而不仅仅是在标准间反弹。当考虑到迁移EOA仍需依赖另一EOA进行授权——原始问题依然存在,只是处于不同的抽象层面。
账户抽象并不是让EOA像传统合同账户一样运作——前者在某种程度上应该能够保持其自主权——并与合同账户的可编程性相结合。完全迁移到合同账户实际上消除了EOA的自主权,使其面临传统合同账户的挑战,并且还有一些额外的挑战。
EOA迁移方案将会在EVM中创造不必要的技术负债,因为一旦实现了原生账户抽象,其功能将变得多余。当账户能天生地利用内置机制访问高级功能时,就没有必要在不同账户标准之间进行迁移。
此外,量子计算日益明显的威胁使得以太坊协议在与其ECDSA和BLS方案进行试验时的时间变得更少。这些方案为大多数加密证明提供支持。基于晶格和哈希的量子抗性方案可能是21世纪2024年的最佳选择,而不依赖ECDSA的智能账户则是解决方案的简单路径。
最终,以上理由使得EOA的可编程性路径被视为一种更可行的方式,以让账户在不进一步确立现有功能的情况下访问抽象的某些特性。重要的是,这都是在原生/链内账户抽象为不远的未来而做的临时安排。
毫无疑问,迁移EOA具有某种向后兼容性和较低开发成本的好处,因为我们只是利用现有的智能钱包基础设施。然而,这一方法因其与全面功能齐全的账户抽象框架的不兼容性(以及本报告中描述的其他问题)而面临挫折。
账户迁移是好的——只是不够好,无法成为以太坊在短期内实现完全账户抽象的途径。下一篇报告将覆盖加速以太坊账户抽象路线图的另一种方法:原生账户抽象。
原生账户抽象旨在直接在协议层确立AA特性,使智能合约账户成为第一类公民。这类提案将减少对ERC-4337这类非协议AA解决方案的依赖,或完全消除对它们的需求,并解决以太坊迄今为止阻碍账户抽象发展的许多问题。
致谢:特别感谢Hadrien Crubois, Nicolas Cosigny, Sam Wilson, Yoav Weiss, Konrad Kopp, Alexander Chopran, Eugenio Reggianini,以及Koray Akpinar为审查和反馈所做的贡献。我们还感谢 SafeDAO 通过OBRA计划资助本报告的工作。
- 原文链接: research.2077.xyz/charti...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!