layout: post title: “[译]ERC 4337:不改变Ethereum协议的账户抽象” date: 2023-05-13 21:27:24+08:00 categories: work tech ——-

原文链接

———-

前言

账户抽象长期以来一直是Ethereum开发社区的梦想。抽象账户可以为个人用户钱包实现__验证逻辑__(nonces, 签名等),而不再使用EVM代码去实现__应用程序逻辑__。这会为钱包设计的创意打开大门,提供一些重要的特性:

  • 多签和社交恢复
  • 更加高效和简单的签名算法(eg. Schnorr,BLS)
  • 后量子安全签名算法(eg.Lamport,Winternize)
  • 可升级性

如今使用一个智能合约钱包可以完成所有这些事情,但以太坊协议本身要求将所有内容打包在源自ECDSA安全保护的外部拥有账户 (EOA) 的交易中,这一事实使得这变得非常困难。每个来自EOA账户的用户操作都将被交易包裹,增加21000的额外gas负担。用户要么需要有另外一个单独的有ETH余额的EOA账户去付gas,或者依赖一个中继系统,而中继系统通常是集中式的。

EIP 2938是修复该问题的一种方式,通过介绍修改一些以太坊协议能够允许从合约地址而不是EOA地址发送顶层的以太坊交易。合约本身将有验证和付gas的逻辑,这些逻辑矿工将检查。然而这需要对协议进行一次重大的修改,而目前协议开发人员正在重点关注the merge和可扩展性。在我们新的提案(ERC 4337)中,我们提供了一个不修改共识协议层但是有同样收益的方式。

ERC 4337如何工作

取代修改共识协议本身的逻辑,我们在更高逻辑层级上复制交易池功能。用户发送UserOperation对象,包含了用户的意图,签名以及为了验证的其他数据。矿工或使用Flashbots的Bundler打包一组UserOperation对象到一个单独的”bundle transaction”,这个”bundle transaction”被包含到Ethereum区块中。

UserOperation mempool

bundler用ETH为bundler交易支付gas费,并通过作为所有单个UserOperation执行的一部分支付的费用获得补偿。Bundlers根据现有矿工mempool中打包原则,将相似fee-prioritization逻辑的UserOperation包含在一起。一个UserOperation看起来像一个交易;他是一个ABI编码的结构,包含以下字段:

  • sender:发起操作的wallet
  • noncesignature:传递到wallet验证函数的参数,因此wallet可以验证一个操作
  • initCode:如果wallet还不存在,用于创建钱包的初始化代码
  • callData:实际执行步骤用什么数据调用钱包

其余的字段用来做gas和fee的管理;完整字段可以在ERC 4337中查看。

wallet是一个智能合约,要求有两个函数:

  • validateUserOp,使用UserOperation作为输入。这个函数应该验证UserOperation的签名和nonce,支付fee,如果验证成功nonce增加,如果验证失败抛出异常。
  • 一个op执行函数,解析calldata为指令,使钱包做出相应的动作。该函数如何解释calldata以及结果是什么是完全开放式的;但是我们期望最常见的操作应该是解释calldata为指令,让钱包进行一次或多次调用。

为了简化钱包逻辑,许多复杂的智能合约确保安全所需要的trickery不在wallet本身,但在一个叫做entry point的全局合约。validateUserOp和执行函数将限制为require(msg.sender == ENTRY_POINT),因此仅受信任的entry point可以发起wallet执行任何操作或只支付gas。entry point仅在带有调用数据calldata的UserOperation完成validateUserOp后才对钱包进行任意调用,所以这足够保护钱包免受攻击。当wallet不存在时,entery point同样负责使用initCode去创建钱包。

Entry ponit control flow when running handleops

Entry ponit control flow when running handleOps

mempool节点和bundlers在关于validateUserOp可以做什么的时候有一些限制:特别是,validateUserOp执行不能读写其他合约的存储,不能使用环境相关opcodes,比如TIMESTAMP,不能调用其他合约,除非这些被调用的合约可证明不会自毁。需要保证bundlers和UserOperation mempool节点的对validateUserOp的__模拟执行__针对指定的UserOperation是ok的,可以包含或转发,且和之后实际包含在以后区块中有相同的效果。

如果UserOperation的验证模拟成功,UserOperation可以保证被包含直到sender账户有其他内部状态变化(由于相同sender的另外一个UserOperation或者另外的合约调用到sender;在任一情况下,该账户触发此条件需要在链上花费7500+gas)。另外,一个UserOperationvalidateUserOp阶段指定gas limit,mempool节点和bundlers将拒绝他,除非这个gas limit非常小(比如,低于200000)。这些限制复制于现行的Ethereum交易的关键属性,以防止DoS攻击。Bundlers和mempool节点可以使用当前Ethereum交易的相似逻辑,以决定是否包含或转发一个UserOperation

和常规以太坊mempool相比,这种设计增加/保持/牺牲了哪种属性

保持属性:

  • 无中心化角色;所有的事情都是通过端对端的mempool完成
  • DoS安全(通过模拟检查的UserOperation保证是可包含的,直到sender有另一个状态变化,这将要求攻击者为每个sender支付7500+gas)
  • 没用用户端钱包设置的复杂性: 用户不用关心他们的钱包合约是否已经发布;钱包存在于特定的CREATE2地址中,如果钱包在第一个UserOperation前不存在,则自动创建一个
  • 完全EIP 1559支持,