> For the complete documentation index, see [llms.txt](https://docs.goodcrypto.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.goodcrypto.app/goodcryptox-zh/qian-bao/nei-zhi-qian-bao/zhi-neng-he-yue-qian-bao/jie-xi-scw-dui-huan.md).

# 解析 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 链接查看该交易在链上的样子：

{% hint style="info" %}
关于区块浏览器链接的说明：在最新版应用中，区块浏览器链接已直接打开您的 AA 交易（UserOp）。如果您看到的是这种情况（“From” 字段显示您的钱包地址），您可以直接跳到 [步骤 5 – AA 交易详情页面](#step-5-open-the-aa-transaction-details-page)。较早的步骤仅在您的链接指向外层打包交易时适用（此时“From” 不是您的钱包）。不过，阅读这些步骤仍然很有用，以更好地理解 SCW 交易的工作原理
{% endhint %}

<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 – 在区块链浏览器中打开该交易**

{% hint style="info" %}
关于区块浏览器链接的说明：在最新版应用中，区块浏览器链接已直接打开您的 AA 交易（UserOp）。如果您看到的是这种情况（“From” 字段显示您的钱包地址），您可以直接跳到 [步骤 5 – AA 交易详情页面](#step-5-open-the-aa-transaction-details-page)。较早的步骤仅在您的链接指向外层打包交易时适用（此时“From” 不是您的钱包）。不过，阅读这些步骤仍然很有用，以更好地理解 SCW 交易的工作原理
{% endhint %}

你点击 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 作为你的存款，将在下一笔交易中自动使用。
