返回博客

ERC4337:以太坊账户抽象标准详解

·0xPM
Web3钱包账户抽象
系列钱包与账户2 / 2
  1. 1Web3钱包与用户体系设计
  2. 2ERC4337:以太坊账户抽象标准详解
  3. 查看系列 →

以太坊原生账户模型将账户分为两类:EOA(Externally Owned Account)和 CA(Contract Account)。这个二元结构有一个根本性限制——只有 EOA 能发起交易,CA 只能被动响应。ERC-4337 的目标是在不修改 L1 共识层的前提下,实现账户抽象——让智能合约具备发起操作的能力,同时保持 EOA 的原生灵活性。

整体流程

  1. 用户创建UserOperation - 用户通过钱包应用创建一个UserOperation对象
  2. 发送到内存池 - UserOperation被发送到专门的内存池(alt-mempool,不是以太坊的交易池)
  3. Bundler打包 - Bundler从内存池中选取多个UserOperation打包
  4. 提交到链上 - Bundler调用EntryPoint合约执行这些操作
  5. 验证和执行 - EntryPoint验证每个操作并执行

关键角色

角色职责
智能合约钱包用户的钱包逻辑合约,定义验签规则、权限控制、限额等
UserOperation用户意图的结构化描述,包含 callData、gas 参数、签名等,不是标准 tx
Bundler一个 EOA,把多个 UserOp 打包成一笔真实交易提交上链,赚取打包费
EntryPoint全网唯一地址的单例合约,所有操作的审核入口,两阶段执行(验证 + 执行)
Paymaster可选模块,实现代付 gas 或 ERC-20 换算支付 gas 的逻辑

详细说明

1. 智能合约账户实现

每个用户的钱包是一个智能合约,需要实现以下接口:

interface IAccount { function validateUserOp( UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds ) external returns (uint256 validationData); }

validateUserOp函数负责:

  • 验证签名是否有效
  • 检查nonce是否正确
  • 如果需要,向EntryPoint存入足够的ETH支付gas
  • 返回验证结果

2. UserOperation结构

UserOperation包含以下关键字段:

{ sender: address, // 智能合约账户地址 nonce: uint256, // 防重放攻击 initCode: bytes, // 如果账户不存在,用于创建账户的代码 callData: bytes, // 要执行的操作数据 callGasLimit: uint256, // 执行调用的gas限制 verificationGasLimit: uint256, // 验证阶段的gas限制 preVerificationGas: uint256, // 额外的gas补偿 maxFeePerGas: uint256, // 最大gas价格 maxPriorityFeePerGas: uint256, // 最大优先费 paymasterAndData: bytes, // Paymaster地址和相关数据 signature: bytes // 用户签名 }

3. EntryPoint合约核心逻辑

EntryPoint是整个系统的核心,主要函数是:

function handleOps( UserOperation[] calldata ops, address payable beneficiary ) external;

执行过程分为两个阶段:

验证阶段(Verification Loop)

对每个UserOperation:

  1. 检查账户是否存在,不存在则用initCode创建
  2. 调用账户的validateUserOp函数
  3. 如果有Paymaster,调用Paymaster的验证函数
  4. 确保有足够的gas费用

执行阶段(Execution Loop)

对每个UserOperation:

  1. 调用账户合约执行callData中的操作
  2. 如果有Paymaster,调用Paymaster的后置处理函数
  3. 计算实际消耗的gas并退款
  4. 将gas费用支付给Bundler

4. Paymaster实现

Paymaster是可选的,用于赞助用户的gas费用:

interface IPaymaster { function validatePaymasterUserOp( UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost ) external returns (bytes memory context, uint256 validationData); function postOp( PostOpMode mode, bytes calldata context, uint256 actualGasCost ) external; }

Paymaster可以实现各种支付策略:

  • 用ERC20代币支付gas
  • 为特定用户免费
  • 根据业务逻辑决定是否赞助

可实现功能

1. 社交恢复

在 validateUserOp 里实现 M-of-N 多签逻辑,将 guardian 地址集合存储在合约 storage 中。恢复流程通常引入时间锁(如 48 小时),防止 guardian 合谋或被社工攻击——在时间窗口内,原主人可以取消恢复请求。Guardian 可以是另一个 EOA、另一部手机,或者其他智能合约。Argent 钱包已在生产环境使用这套机制。

2. Gas 抽象

Paymaster 在 EntryPoint 的 validation phase 介入,分两种模式:Sponsored Paymaster 由项目方预存 ETH 到 EntryPoint,对白名单用户免 gas;Token Paymaster 则通过 Chainlink 等预言机获取 ERC-20/ETH 实时汇率,在 validatePaymasterUserOp 阶段锁定用户代币,在 postOp 阶段按实际消耗结算退款。用户全程感知不到 ETH 的存在。

3. 批量操作

callData 编码为 executeBatch(calls[]),EntryPoint 单次调用账户合约,账户合约内部顺序执行多个子调用。关键在于原子性控制——可以选择"一个失败全部回滚"或"失败跳过继续执行"两种策略,根据业务场景在合约里自行实现。典型用例:Uniswap 的 approve + swap 从两笔交易合并为一笔,节省约 30-40% gas。

4. Session Key

向合约注册一个临时 signer,存储时附带精细的权限约束:允许调用的目标合约地址白名单、单笔转账金额上限、过期时间戳。验签逻辑判断:如果是普通操作用主密钥验证,如果签名来自已注册的 session key 则走权限校验路径。链游场景里,游戏合约拿到 session key 后可在一小时内自动签名操作,时间到了权限自动失效,主资产始终安全。

5. 限额保护

在账户合约的 execute 函数里解码 callData,提取目标地址和转账金额,与预设规则比对。日限额通常用滑动时间窗口实现(记录最近 24 小时的累计金额),超出则 revert。可以叠加多层规则:单笔上限 + 日总上限 + 高风险合约黑名单。即使私钥泄露,攻击者也只能在限额内操作,为用户争取响应时间。

6. 自动化执行

账户合约预存执行条件(时间、价格阈值等),链下 keeper 网络(Gelato、Chainlink Automation)监听条件是否触发,满足时由 keeper 构造并提交 UserOperation,gas 费可由 Paymaster 代付或从用户账户扣除。相比传统方案,整个流程无需用户在线,也不需要信任中心化服务器——keeper 无法超出合约规则执行任何操作。

优势与风险

优势

无需协议升级即可部署;功能可组合,钱包逻辑完全自定义;Paymaster 机制极大降低用户门槛;L2 上 gas 开销影响有限

风险

Bundler 生态目前较集中,存在审查风险;validateUserOp 实现 bug 可能被绕过;整体攻击面比 EOA 大;固定 gas 开销在 L1 仍偏高

(Bundler 去中心化是当前最值得跟进的方向,ERC-7562 提案在试图解决这个问题。)

目前可用的实现

项目描述
Biconomy模块化 AA SDK,大量 DApp 集成,开发者友好
ZeroDevKernel 架构,插件化,支持多种验签方式
Alchemy Account Kit配套 Rundler 高性能 Bundler,适合高频场景
Stackup提供完整 AA 基础设施,含 Bundler + Paymaster 服务
Candide移动端钱包,Safe 合约为底层

评论

加载中…