---
title: "什么是 user operations？"
description: "定义、参数及工作原理"
---

# 什么是 user operations？

用户操作是包含交易细节的对象，代表发送者的智能合约账户执行。用户操作是一种伪交易对象，它使账户抽象得以实现，而无需对以太坊及支持[ERC-4337](https://www.alchemy.com/overviews/what-is-account-abstraction)的二层区块链进行共识层改动。

要开发智能合约钱包（SCW），或让去中心化应用兼容 SCW，理解定义用户操作的各个参数、用户操作字段在构造过程中如何被填充、用户操作如何被 Bundler 打包、以及如何被 Paymaster 验证和执行，会很有帮助。

<CalloutBlock>
  使用我们的 Embedded Accounts 和账户抽象基础设施，让新用户能够[创建嵌入式邮箱和密钥对钱包](https://www.alchemy.com/smart-wallets)！
</CalloutBlock>

## 观看：在 Solidity 中构建和执行用户操作

<ExternalVideo
  url="https://youtu.be/NM04uxcCOEw?si=GP-JehvonrZ_6qtJ"
  provider="youtube"
  providerUid="NM04uxcCOEw"
/>

## **用户操作中包含哪些字段？**

用户操作（UO）包含与常规交易类似的字段（例如 sender、to、calldata、maxFeePerGas、maxPriorityFee、signature 和 nonce），但也有一些新字段是用户操作结构体特有的，包括 callGasLimit、verificationGasLimit、preVerificationGas 和 paymasterAndData。

UO 字段的定义可以在[官方 ERC-4337 规范](https://eips.ethereum.org/EIPS/eip-4337)中找到。以下是简要总结：

- **callGasLimit** - 主执行调用所使用的 gas
- **verificationGasLimit** - 完成验证步骤所使用的 gas
- **preVerificationGas** - 支付给 Bundler，用于覆盖预验证执行和 calldata 成本的 gas
- **paymasterAndData** - 赞助方 Paymaster 的地址，以及要发送给 Paymaster 的数据

关于[用户操作的设计与架构](https://www.alchemy.com/overviews/what-is-account-abstraction)的说明，可以阅读“You Could Invented Account Abstraction”系列的第一部分，作者是 **David Philipson**，Alchemy AA 基础设施团队的工程师。

接下来，我们来学习正确填充用户操作字段的标准流程。

## **发送用户操作的流程是怎样的？**

向[Bundler](https://www.alchemy.com/overviews/what-is-a-bundler)发送用户操作（user op）的典型流程包含多个步骤：

1. 构造一个部分填充的用户操作，填入 sender、nonce、initCode 和 callData
1. 通过 eth_estimateUserOperationGas 向 Bundler RPC 估算该部分用户操作的 gas
1. 填充 preVerificationGas、verificationGasLimit、callGasLimit
1. 如果使用的 Paymaster 不依赖用户操作的具体内容，例如 [ERC20](https://www.alchemy.com/overviews/erc20-solidity) Paymaster，可以在此处填充 paymasterAndData。
1. 估算该操作所需的 gas 费用，并填充 maxFeePerGas 和 maxPriorityFeePerGas
1. （可选）将用户操作发送给赞助方 Paymaster 进行签名，并填充 paymasterAndData
1. 这一步必须在此处完成，因为 Paymaster 的签名需要上述所有字段都已填充。
1. 对用户操作签名，填充 signature，并通过 eth_sendUserOperation 将用户操作发送给 Bundler

虽然开发者可以使用原生的 [ethers.js](https://www.alchemy.com/dapps/ethers-js) 来获取每个用户操作字段的值，但也有一些 web3 开发者工具可以让 UO 构造更简单。

## **开发者可以使用什么工具来构造用户操作？**

像 Alchemy 开源的 AA SDK 这样的用户操作构造工具，能让构建用户操作比使用原生 ethers.js 更简单。

### **Alchemy 的 AA SDK**

Alchemy 的 AA SDK 基于 viem 构建，为开发者提供了一个轻量级的包。[GitHub 上的 aa-sdk](https://github.com/alchemyplatform/aa-sdk) 也通过 aa-ethers 库支持 ethers.js 的 signer 和 provider。

使用 aa-sdk 构造用户操作的主要优势之一，是它提供了两个实用方法：

1. **sendUserOperation** - 处理 gas 估算、请求 paymasterAndData、签名等
1. **sendTransaction** - 将交易对象数据（from、to、data 和 value）转换为用户操作

构造用户操作的操作顺序比较复杂，而 Alchemy 的 AA-SDK 通过运行一系列操作简化了 UO 的构造过程：先用 **getDummyPaymasterData**，再用 **estimateGas** 估算 gas，然后是 **getFeeData**，最后是 **getPaymasterAndData**。

在获取用户操作字段的值之后，它会接收目标地址、callData 以及一个可选的 value，来构建并签名用户操作。然后它会将该用户操作发送给 Bundler，并接收该用户操作的哈希值。

如果你想使用 Alchemy 的 Paymaster、其他的 Paymaster，或者计划为你自己的 SmartAccounts 添加支持，请阅读 [Alchemy AA SDK 文档](https://www.alchemy.com/docs/wallets/reference/aa-sdk/core)，其中详细说明了如何轻松创建 UO。

<ExternalVideo
  url="https://youtu.be/7aJ5bonMSyQ?si=P6ZANXn3HQYUssJr"
  provider="youtube"
  providerUid="7aJ5bonMSyQ"
/>

## **用户操作是如何被添加到用户操作内存池的？**

在用户操作被添加到内存池之前，它必须通过一系列检查，以确保其符合 ERC-4337 规范中所述的预期行为。用户操作还必须通过验证模拟检查，以确认其有效，并能够支付自身的 gas 费用（无论是通过发送者的钱包，还是通过 Paymaster 的赞助策略）。

### **1. 检查用户操作的有效性**

最初的一系列检查在 ERC-4337 规范的“Client behavior upon receiving a UserOperation”一节中有说明，以下是简要总结：

- sender 是一个已存在的合约，或者 initCode（用于创建合约）不为空（但不能两者都满足）
- 如果 **initCode** 不为空（因为该用户操作要创建一个账户），需判断该工厂合约是否已质押（staked）
- **verificationGasLimit** 足够低（小于或等于 **MAX_VERIFICATION_GAS**）
- **preVerificationGas** 足够高，能够支付 calldata gas 和额外开销费用
- **paymasterAndData** 要么为空，要么以 Paymaster 地址开头
- 如果存在 Paymaster，它必须在链上有非空代码、有足够资金支付该用户操作，且未被封禁
- **callgas** 至少要达到一次带非零值的 **CALL** 所需的成本
- **maxFeePerGas** 和 **maxPriorityFeePerGas** 要高于客户端能接受的最低值
- 发送者在内存池中没有其他用户操作（或者该用户操作是构造用来替换已有条目的）

有许多规则会影响这些检查，规范中对此有完整说明。

对于这篇关于用户操作的介绍性文章，我们只想传达用于判定用户操作有效性的高层检查内容。

### **2. 模拟用户操作**

一旦用户操作通过了这些基础检查，客户端需要模拟该用户操作，以验证它能够支付其执行费用，无论是使用自身资金还是通过 Paymaster。

要模拟一个用户操作，Bundler 会调用 **simulateValidation()** 方法，该方法接着会调用发送者账户上的 **validateUserOp** 函数，或者，如果将使用 Paymaster 来赞助执行该用户操作所需的 gas 费用，则调用 Paymaster 合约账户上的 **validatePaymasterUserOp**。

在调用 **simulateValidation()** 方法之后，它会以 **ValidationResult** 响应回退（revert）。函数被回退是预期行为，这被视为一次成功的结果。

如果 **ValidationResult** 以其他错误回退，那么该用户操作未通过验证模拟，不会被添加到内存池中。如果用户操作返回 **sigFail**，则会被排除在内存池之外；如果 **validUntil** 响应已过期，UO 也可能被排除在内存池之外。

**注意：** 如果用户操作中存在 initCode，账户工厂将创建一个账户，随后模拟过程会使用这个新创建的账户继续进行。

现在用户操作已经完成构造、检查、模拟并添加到内存池中，接下来它可以被发送到入口点合约（entry point contract）进行验证和执行！

### **用户操作是如何被验证和执行的？**

为了让用户操作中的交易细节能够发布到链上，入口点合约需要验证该用户操作，如果该 UO 通过验证，入口点合约就会执行该交易，然后向 Bundler 偿还其支付的 gas 费用。

**用户操作验证和执行的基本步骤是：**

1. Bundler 通过 handleOps() 方法将用户操作发送给单例入口点合约
1. 对于每个操作，入口点合约会在该操作的发送者钱包上调用 validateOp\*
1. 如果任何操作未通过验证步骤，它们会被丢弃
1. 接下来，在每个操作的发送者钱包上调用 executeOp，并跟踪使用了多少 gas
1. 从发送者钱包或 Paymaster 向 Bundler 转账 ETH，以支付执行每个操作所消耗的 gas

\*所有验证都会先执行完毕，之后才会执行所有通过验证的用户操作。

下图展示了入口点合约如何代表发送者的智能合约钱包对用户操作进行验证和执行：

<ImageBlock
  src="https://media.alchemy.com/1703862507-user-operations-validations-executions.png"
  alt="用户操作如何被验证和执行"
  width={960}
  height={540}
/>

用户操作是一种伪交易对象，它使智能合约钱包能够作为用户在以太坊及其等效二层网络上的主钱包发挥作用。智能合约钱包引入了[web3 用户体验优势](https://www.alchemy.com/overviews/smart-contract-wallet-benefits)，使区块链更易于使用，而这一切都得益于[以太坊及二层网络上的 AA 基础设施提供商](https://www.alchemy.com/account-abstraction)。

如果你的[web3 产品支持智能合约钱包](https://www.alchemy.com/docs/how-to-make-your-dapp-compatible-with-smart-contract-wallets)，欢迎探索 Alchemy 的 AA 基础设施，包括面向 Ethereum、Polygon、Arbitrum、Optimism 以及 Sepolia 等常用测试网的 Gas Manager API 和 Bundler API！
