# 解析 SCW 兑换

使用智能合约钱包（SCW）时，交易路径与传统以太坊/EVM 钱包有很大不同。这种差异可能令人困惑，尤其是在出现问题时。但一旦你了解流程中的关键参与者，以及如何在应用和区块链浏览器上逐步读取发生了什么，事情就会开始变得清晰。

让我们一起逐步查看。

***

#### 从一次点击到链上执行：实际发生了什么

当你在应用中点击“兑换/Swap”时，感觉像是一个单一操作。实际上，你启动的是一个建立在以太坊账户抽象（ERC-4337）之上的多层流程。你的交易不会像普通钱包那样直接发送到区块链。相反，它会绕道而行：

1. 我们构建路由。我们请求路由引擎（如 1inch）为你的兑换找到最佳路径，并进行模拟以确保其可行。我们估算 Gas，验证你拥有相应代币，并将操作指令打包成一种特殊格式：一个 `UserOperation`.
2. 一个 `bundler（打包器）` 介入。这是一个链下角色，负责将 UserOperations 提交到区块链。它会检查你的操作、确保其有效，并为你预付 Gas（稍后获得报销）。
3. 你的 UserOp 通过 `EntryPoint` 智能合约进入区块链。把 EntryPoint 想象成所有 SCW 交易必须通过的唯一入口。EntryPoint 会进行最终检查，如果一切正常……
4. EntryPoint 会指示你的智能合约钱包（SCW）执行兑换。你的 SCW 调用路由器（例如 1inch），路由器调用资金池，代币移动，输出回到你的钱包。

总结一下：你点击兑换 → 我们模拟 → bundler 提交 → EntryPoint 验证 → 你的 SCW 执行。

***

#### 让我们看一个真实示例

既然我们了解了高层流程，让我们看看在一次真实兑换中这是如何发生的：先在应用中，再在链上查看：

<figure><img src="/files/8aadab4e6d3bb201363f1b5109b0198276470173" alt=""><figcaption></figcaption></figure>

我们看到的是：

* 我们用 1 USDC 兑换得到了 0.765 KTA。
* 该兑换在 Base 上执行（注意币符号上的 Base 图标）。
* 我们支付了：
  * 0.03 美元的 Gas（以 ETH 支付）
  * 0.22% 的兑换费用支付给 goodcryptoX
  * 0.05% 的路由器费用支付给 1inch
* 路由很简单：100% 通过一个 Uniswap v4 池。
* Bundler：Alchemy（参见上文第 2 步回顾）
* 如果交易已经到达区块链并被写入区块（即使失败），会出现浏览器链接

到目前为止，一切良好。接下来，让我们点击 BaseScan 链接查看该交易在链上的样子：

<figure><img src="/files/20409e6731868a7a56a30713c26dec1cd9614420" alt=""><figcaption></figcaption></figure>

**来自：** 这不是你的钱包——是 Alchemy 的 bundler。这是预期之内，因为 bundler 提交了交易。

**到：** EntryPoint（v0.6.0）。同样是预期之内——所有 SCW 交易都通过这里进入。

**内部交易（Internal Transactions）：** 显示交易中本原生代币（在 Base 上为 ETH）的流动。我们看到的是：

* 我们的钱包（…0A5）向 EntryPoint 发送了 ETH 作为 Gas 费用。
* EntryPoint 按实际 Gas 成本向 bundler 报销（因为 bundler 代表你预付了 Gas；参见上文第 2 步）。任何剩余的 ETH 会留在 EntryPoint 作为你未来交易的存款。

**ERC-20 转账：** 显示实际的代币流动：

我们的钱包并未直接发送 USDC。相反，USDC 代币合约（…2A8）处理并发起了这些转账。这是正常的：在 EVM 链上，代币转账由代币合约在收到来自你的智能合约钱包的指令后执行。

1. USDC 合约将我们的 1 USDC 拆分为三个转账：
   * 0.0022 USDC 到我们协议的费用钱包（…608A）
   * 0.0005 USDC 到 1inch 的费用钱包（…1DE5）
   * 剩余的 0.9973 USDC 到 Uniswap v4 路由器（…Universal Router）
2. Uniswap v4 路由器 将其传递给 Uniswap v4 池管理器（一个管理所有 v4 池的单一合约）。
3. 池管理器执行了兑换：USDC 进入 → KTA 出来。
4. KTA 通过 1inch 的聚合路由器返回并转发到我们的钱包（…0A5）。

***

### 🧩 如何解析失败的 SCW 交易

既然我们了解了智能合约钱包（SCW）兑换的工作原理——并已经演示了成功的交易——让我们用相同的工具来解析一次失败的交易。

我们将使用另一个真实案例：一次在以太坊上将 ETH 换成代币的交易，该交易在 EntryPoint 合约内部失败，因为没有足够的 ETH 同时覆盖兑换和 Gas 费用。

好，所以你在应用中看到“错误/Error”作为兑换状态，或收到推送通知说兑换失败。你该怎么做？

***

#### 步骤 1 — 在 goodcryptoX 中检查订单详情

在此情况下你会看到如下内容：

<figure><img src="/files/8bbf3ccd8c8759afa3cbc7371a77f7279d84fb38" alt=""><figcaption></figcaption></figure>

使用我们之前开发的框架，你会很快注意到：

* 兑换状态是 `Error（错误）` *（失败？）*  &#x20;
* 没有显示错误信息 *（这不寻常）*
* 有 Gas 费用 *（到达区块链了吗？）*
* 显示有路由 *（模拟通过了吗？）*
* 有区块链浏览器的链接 *（我可以在区块链上检查该交易！）*

让我们验证你的直觉：

* 该 `Error（错误）` 状态 表示兑换失败
* 应同时有可读的错误信息（从原始信息翻译）和原始错误。缺少错误信息绝对意味着出现了异常情况
* 有 Gas 费用确实意味着交易已经到达区块链并发生了一些链上活动（消耗了 Gas）
* 路由确认交易模拟通过并产生了明确的执行路径
* 浏览器链接确认交易到达了区块链——即使它失败了。我们应该打开其中一个链接进一步调查

***

**步骤 2 – 在区块链浏览器中打开该交易**

你点击 Etherscan 链接查看发生了什么：

<figure><img src="/files/11d0fd0c7d04f66ed06db05d2fbc479b8842e8b2" alt=""><figcaption></figcaption></figure>

乍看之下，情况变得更令人困惑：

* 状态显示 ✅ Success（成功） *— 等等，什么？！*
* 但我们已经知道该兑换 **并未完成**
* 在 “To” 字段（EntryPoint）下，有一条小的黄色信息：

  > *“<mark style="color:$warning;">虽然发生了一个或多个错误 \[execution reverted] 合约执行已完成</mark>”*

那到底是怎么回事？

记住我们之前讲过的 SCW 交易流程：

* bundler 将你的兑换打包成一个 `UserOperation` （一个包含你兑换逻辑的数据包）
* 然后将其发送到 EntryPoint 智能合约
* EntryPoint 验证它（检查你的余额、签名和 nonce）
* 如果一切检查通过，它会执行你的意图——调用路由器、资金池并移动代币。

但从区块链的角度来看，整个事情看起来只是“bundler 向 EntryPoint 发送数据”。&#x20;

在 SCW 术语中，这个步骤被称为 `外部` 交易。

而且该交易确实成功了：数据被传递，EntryPoint 开始运行其内部逻辑。因此顶部显示 ✅ Success。

***

但浏览器出于礼貌，仍会告诉你内部有事情失败了， *在* EntryPoint 内部，用那条小黄条提示。对于浏览器来说，内部的失败不足以将整个交易标记为失败。

现在，在概览（Overview）标签上另一个细节跳了出来：

* 大约 **$6** 价值的 ETH 从你的钱包发送到 EntryPoint（作为 Gas 的预付）。
* 只有 **$2.3** 价值的 ETH 被报销给 bundler。
* 而顶部显示的交易费用更低——大约 **$2.15**.

乍一看，这些数字似乎不一致。在继续调查之前，让我们先把这部分拆开来说明

***

**步骤 3 – 了解 Gas 差异**

下面是明细：

* **SCW → EntryPoint** （约 $6）：这是 Gas 的预付。EntryPoint 总是收取比运行 UserOp 所需更多的金额以确保你的 UserOp 能执行。
* **EntryPoint → Bundler** （约 $2.3）：这是实际的 Gas 报销。这是 **你为这次失败尝试实际支付的金额，** 。
* **交易费用（Transaction Fee）** （约 $2.15）：这是 bundler 为将你的 UserOp 发送到 EntryPoint 所花费的费用。它看起来更低，是因为 EntryPoint 在验证和报销 bundler 时本身使用了额外的 Gas——那部分额外费用由你承担。

经验法则：

> 👉 你实际的 Gas 成本始终是 EntryPoint ➜ Bundler 的报销（而不是顶部显示的“交易费用”）

你预付的金额（约 $6）与被报销的金额（约 $2.3）之间的差额并没有消失。它留在 EntryPoint 作为你的存款，将自动用于你下一笔交易。

***

**步骤 4 – 检查 AA Transactions（AA 交易）标签**

在浏览器上，你会看到一个 **AA Transactions** 标签（AA = Account Abstraction，账户抽象）。这是智能合约钱包活动所在的位置，因为 SCW 在账户抽象（ERC-4337）下运行。

让我们从概览切换到该标签：

<figure><img src="/files/bfd326cd68b486e45e2a9d84aadae5aa80ac36fc" alt=""><figcaption></figcaption></figure>

在这里你终于会看到我们的 UserOperation 被列为 bundler 外部交易内的一个单独条目：

* "From" 字段现在显示 *我们的钱包地址*，确认这是我们的操作。
* 有一个单独的 AA 事务哈希，与外部交易哈希不同。为什么？
  * 外部交易哈希属于包含你 UserOp 的 Bundler->EntryPoint 交易（该交易可能包含来自不同用户的多个 UserOp）。
  * AA 事务哈希是你 *的* UserOperation 在该打包内的唯一标识符。

这是打包的关键理念：

* 一个 bundler 可以将许多 UserOps 打包到一个交易中。
* 每个 UserOp 都有自己的 AA 事务哈希，因此可以在打包内被单独跟踪。
* 在我们的案例中，因为这是一个较早的交易（400 多天前），SCW 仍然很少，打包内只包含我们的 UserOp——这就是该标签显示 “AA Transactions (1)” 的原因。在更新的交易中，你经常会看到多个 UserOp 被批量打包在一个包中。

在此视图中，你还会注意到在你的 AA 事务哈希旁边有一个 <mark style="color:红色;">(!)</mark> 图标——确认你的兑换没有执行成功。

下一步是点击 AA 事务哈希。这会打开专门的 UserOperation 页面，你将在那里看到我们尝试兑换的完整详情——费用、转账以及失败点。

***

#### 步骤 5 – 打开 AA 交易详情页

点击 AA 事务哈希会将你带到该 UserOperation 的专用详情页面：

<figure><img src="/files/ff1429edede0a417b4c44a4e7a5a42de0428d05c" alt=""><figcaption></figcaption></figure>

在这里你终于可以清楚地看到我们实际的兑换尝试：

* 状态：  <mark style="color:红色;">x 失败（Fail）</mark> （这次没有歧义）
* From：你的智能合约钱包地址
* AA 交易费用：约 0.00231 ETH（约 $2.31）。这是你实际支付的 Gas 成本——即报销给 bundler 的金额。
* 内部交易：一笔约 0.00145 ETH（约 $6.36）从你的 SCW 到 EntryPoint（作为 Gas 预付）。没有其他转账发生，这证实兑换本身从未执行。
* Bundle 交易哈希：也会显示，链接回外部的 bundler 交易。

该页面最终与您的直觉相符：这才是真正的交易——代表你兑换尝试的 UserOperation。

这几乎就结束了我们的调查。但既然我们已经走到这一步，让我们也点击 **Internal Txns（内部交易）**.

***

#### 步骤 6 – 检查 Internal Transactions（内部交易）标签

在 AA 交易视图内切换到 Internal Txns 标签：

<figure><img src="/files/fbbfeaad8461a6e0d510953c02680d62abfa395c" alt=""><figcaption></figcaption></figure>

在这里你可以看到 EntryPoint 代表你尝试执行的逐步操作：

1. ✅ 从你的 SCW → EntryPoint 转账（约 0.00145 ETH，约 $6.36）= Gas 预付。此操作成功。
2. ❌ 从你的 SCW → Uniswap Universal Router 执行（约 0.002 ETH）= 试图执行兑换。此操作失败。

该分解说明了失败的原因：

* 你成功地将 ETH 发送到 EntryPoint 作为 Gas 预付。
* 但当 EntryPoint 试图将 ETH 转发给 Uniswap 以执行兑换时，该尝试失败了。

要获取最详细的分解，请打开日志（Logs）标签。

***

#### 步骤 7 – 检查 Logs（日志）标签

点击 Logs（3）：

<figure><img src="/files/44c0b66dd2bcd324e7c413dd2205dd26a4c7eab5" alt=""><figcaption></figcaption></figure>

在这里你会找到三个关键事件：

* **Deposited（已存入）** → 确认你的 Gas 预付已被 EntryPoint 接收。
* **BeforeExecution（执行前）** → 显示 EntryPoint 已开始处理你的 UserOperation。
* **UserOperationEvent（用户操作事件）** → `success: False（成功：否）` ——这是链上对你的 UserOp 失败的规范记录。

***

**实际发生的情况（综合说明）**

此类失败特定于在 EVM 上使用 SCW 的兑换场景，且输入为本原生代币（如 ETH、BNB、MATIC…）的情况。

* 差距在于：无论是 bundler 还是 EntryPoint 都不会检查你是否有足够的 **本原生代币** 同时覆盖 Gas 预付和兑换本身。他们只分别检查——“够支付 Gas 吗？”和“够兑换吗？”。这就是模拟通过的原因。
* 我们已在应用中为这些情况构建了一个保险措施，在界面中提醒你 Gas 可能不足。但由于模拟看起来正常，你仍然可以继续点击确认。
* 一旦你确认，bundler 将你的 UserOperation 提交给 EntryPoint。
* EntryPoint 拉入了约 6 美元的 ETH 作为预付。
* 当它尝试执行兑换时，剩余的 ETH 不足以同时覆盖兑换 *和* 和预付金额。
* 兑换调用在 EntryPoint 内部回滚（revert）。
* 你仍然支付了约 $2.3 的 Gas（作为对 bundler 的报销）。
* 未使用的约 $3.7 留在 EntryPoint 作为你的存款，将在下一笔交易中自动使用。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.goodcrypto.app/goodcryptox-zh/qian-bao/nei-zhi-qian-bao/zhi-neng-he-yue-qian-bao/jie-xi-scw-dui-huan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
