Erc 4337
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区块中。
bundler用ETH为bundler交易支付gas费,并通过作为所有单个UserOperation
执行的一部分支付的费用获得补偿。Bundlers根据现有矿工mempool中打包原则,将相似fee-prioritization逻辑的UserOperation
包含在一起。一个UserOperation
看起来像一个交易;他是一个ABI编码的结构,包含以下字段:
sender
:发起操作的walletnonce
和signature
:传递到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
mempool节点和bundlers在关于validateUserOp
可以做什么的时候有一些限制:特别是,validateUserOp
执行不能读写其他合约的存储,不能使用环境相关opcodes,比如TIMESTAMP
,不能调用其他合约,除非这些被调用的合约可证明不会自毁。需要保证bundlers和UserOperation
mempool节点的对validateUserOp
的__模拟执行__针对指定的UserOperation
是ok的,可以包含或转发,且和之后实际包含在以后区块中有相同的效果。
如果UserOperation
的验证模拟成功,UserOperation
可以保证被包含直到sender
账户有其他内部状态变化(由于相同sender的另外一个UserOperation
或者另外的合约调用到sender;在任一情况下,该账户触发此条件需要在链上花费7500+gas)。另外,一个UserOperation
为validateUserOp
阶段指定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支持,