> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tenderly.co/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Server 示例

> 使用 Tenderly MCP Server 与 Claude 完成常见工作流的分步演示。

以下演示展示 Claude 如何使用 [Tenderly MCP Server](/ai-tools/overview) 工具完成真实的开发任务。如果您尚未连接，请先阅读 [MCP Server 快速入门](/ai-tools/quickstart)。您无需按名称调用工具，只需描述您想做的事，Claude 会处理其余步骤。

示例大致按活动分组：

* **设置与预检**：启动环境、为钱包注资、在签名之前检查交易。
* **调试与事后分析**：弄清一笔交易为何失败、资金去哪儿了，或者一笔 swap 为何返回低于预期的金额。高级追踪导航工具在此处尤为出色。
* **Virtual Environment 工作流**：冒充、多步骤测试、快照、时间旅行、代币余额覆盖。
* **优化与检查**：gas 拆解、合约元数据。

## 创建 Virtual Environment 并为钱包注资

**如何提问：**

> "Create a Virtual Environment forked from Ethereum mainnet and fund my wallet 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 with 100 ETH."

**Claude 会做什么：**

1. 调用 `list_projects` 查找您的项目，然后调用 `set_active_project` 选择一个。
2. 调用 `get_networks` 找到 Ethereum Mainnet 的网络 ID。
3. 使用网络 ID 调用 `create_vnet`，创建一个 fork 的环境。新的 Virtual Environment 自动设为激活。
4. 使用您的钱包地址调用 `fund_account`，将余额设置为 100 ETH（十六进制 wei）。自动在激活的 Virtual Environment 上运行。
5. 返回 Virtual Environment 的详情，包括 **Admin RPC** 和 **Public RPC** URL，可在 Hardhat、Foundry 或任何 Web3 库中使用。

**您能得到：**

一个从最新 Mainnet 状态 fork 的正在运行的 Virtual Environment，您的钱包已注资，还有可以直接放入您开发框架配置的 RPC URL。

***

## 模拟一笔 Uniswap swap

**如何提问：**

> "Simulate a swap of 1 ETH for USDC on Uniswap V3 from 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 on Ethereum mainnet. Show me the expected output and any token transfers."

**Claude 会做什么：**

1. 调用 `simulate_transaction`，传入 Uniswap V3 router 地址、您的发送者地址、swap calldata 和 1 ETH 作为 value。
2. 模拟针对当前 Mainnet 状态运行，返回：成功/回滚状态、gas 消耗和解码后的方法名。
3. 调用 `get_simulation_asset_transfers` 展示所有代币变动，包括流入的 ETH 和流出的 USDC。
4. 调用 `get_simulation_balance_changes` 展示对您余额的净影响，附带美元价值。

**您能得到：**

精确的 USDC 输出、gas 成本以及每笔资产转移的明细。如果 swap 会 revert（例如滑点过高），您会得到解码后的 revert 原因。

***

## 在发送前对交易进行预检

**如何提问：**

> "I'm about to call `approve` on 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 to give 0xE592427A0AEce92De3Edee1F18E0157C05861564 unlimited USDC allowance. Simulate it first and show me exactly what approvals and state changes it will create."

**Claude 会做什么：**

1. 调用 `simulate_transaction`，以您的钱包作为发送者、代币合约作为接收者，并传入 `approve` calldata。
2. 调用 `get_simulation_exposure_changes` 展示每笔授权和额度变更——哪个 spender 得到了什么权限，以及多少。
3. 调用 `get_simulation_state_changes` 展示被修改的具体存储槽。

**您能得到：**

正在授予的确切授权（spender 地址、代币、金额）、确认额度槽发生变化的存储差异，以及交易是否会成功。在与不熟悉的合约交互，或希望在签名前验证 calldata 时非常有用。

***

## 调试一笔失败的链上交易

**如何提问：**

> "Why did transaction 0x6c5df5a1e6b34e2432ae19706e38a84239495cdbf40c2a9d4d79806443c4aa0d revert on Ethereum?"

**Claude 会做什么：**

1. 使用交易哈希调用 `trace_transaction`。返回状态（`false` = 回滚）、gas 消耗、解码后的方法名和错误消息。
2. 调用 `get_simulation_call_trace` 获取完整的内部调用树——每次函数调用，包含解码后的名称、输入、输出，以及具体是哪个调用失败。
3. 调用 `get_simulation_events` 查看 revert 点之前发出的事件。
4. 可选调用 `get_simulation_state_changes` 查看直到失败为止被修改的状态。

**您能得到：**

清晰地说明具体是哪次内部调用失败、解码后的 revert 原因（例如 `"ERC20: transfer amount exceeds balance"`），以及完整的调用追踪，让您能看到通往失败的执行路径。

***

## 在深度嵌套的交易中找出 revert 的根本原因

**如何提问：**

> "Transaction 0x... reverted on Ethereum. It's a complex DeFi call with lots of internal calls, find the actual error and show me the path that led to it."

**Claude 会做什么：**

1. 调用 `trace_transaction` 获取顶层摘要并确认 revert。
2. 调用 `find_failures` 列出交易中每个失败的调用，而不仅仅是最外层。这会同时暴露原始 revert 以及任何包装的 `require` 或 try-catch 失败。
3. 调用 `get_error_path` 返回从根调用到最深失败调用的追责链条，每一层都包含解码后的输入和输出。
4. 如果仍有节点存在被截断的子节点，则对特定位置调用 `get_call_trace_node` 以展开。

**您能得到：**

最深失败处的确切合约、函数和解码后的 revert 原因，以及导致该处失败的完整调用链。比翻阅一个 200 次调用的 `get_simulation_call_trace` 输出快得多。

***

## 导航一个非常大的追踪

**如何提问：**

> "This transaction has hundreds of internal calls and `get_simulation_call_trace` is truncated. Help me understand its structure and drill into the part that matters."

**Claude 会做什么：**

1. 调用 `get_trace_stats` 报告总调用数、最大深度、错误数和唯一合约数——快速的大小检查，决定策略。
2. 调用 `get_trace_skeleton` 获取压缩的调用树：每个节点的函数名、合约、深度和错误标志，不含解码参数。
3. 使用 skeleton 中的 `absolute_position` 值识别有意思的子树（一个失败分支、一个特定协议或一个可疑合约）。
4. 调用 `get_call_trace_node` 展开该子树，附带完整解码的输入和输出。
5. 可选调用 `get_subtree_events` 和 `get_subtree_state_changes` 仅查看该子树的事件和存储差异。

**您能得到：**

一张交易结构地图，然后只针对您关心的部分获得完整细节，而无需将数千次调用加载到上下文中。

***

## 在追踪中搜索特定合约或函数

**如何提问：**

> "Did this transaction ever call `transferFrom` on USDC? If so, show me every call with the decoded args."

**Claude 会做什么：**

1. 调用 `search_call_trace`，以 USDC 地址和 `transferFrom` 作为过滤条件，仅返回匹配的调用，包括解码后的输入、输出和绝对位置。
2. 对于任何有意思的匹配，调用 `get_call_trace_node` 获取其周围完整的嵌套上下文。

**您能得到：**

一份有针对性的匹配调用列表，而不是完整追踪。对回答大型交易中 "X 是否发生了" 的问题、以及审计一个已知高风险的 selector 是否被调用非常有用。

***

## 追踪一笔交易中的资金流向

**如何提问：**

> "For transaction 0x... on Ethereum, show me who sent what to whom, in order, with USD values."

**Claude 会做什么：**

1. 使用交易哈希调用 `get_transaction_fund_flow`。返回按顺序排列的代币和原生转移，每一笔都有 from/to 地址和美元价值，以及每个地址的净流量。
2. 可选对任何不熟悉的地址调用 `get_contract_info` 以识别其身份（协议 router、pool、treasury 等）。

**您能得到：**

一份按时间顺序的资金地图，以及每个地址的净流量，非常适合理解 MEV bundle、不熟悉的 DeFi 交互，或验证多跳 swap 是否按预期移动了资金。仅限链上交易。

***

## 调试失败的 Safe 多签批处理执行

**如何提问：**

> "Our Safe batch execution at 0x... reverted on Ethereum. The batch has 12 calls. Which one actually failed and why?"

**Claude 会做什么：**

1. 调用 `trace_transaction` 确认 revert 并获得顶层方法（`execTransaction` 或 `multiSend`）。
2. 调用 `get_trace_stats`——Safe 批处理很快会展开成大型追踪，因此统计信息决定下一步。
3. 调用 `find_failures`——因为 `multiSend` 在任何子调用失败时通常会 revert 整个批处理，这是查看 12 个操作中具体哪个爆掉的最快方式，而不仅仅是外层 Safe 的 revert。
4. 对失败的子调用调用 `get_error_path`，获得每一层完整解码的输入/输出链条。
5. 如果任何相关节点被截断，可选调用 `get_call_trace_node`。

**您能得到：**

批处理内部具体失败的那次子调用，包含解码后的目标、函数、参数和 revert 原因，而不是一个没有上下文的通用 "GS013" Safe 错误。

***

## 对漏洞攻击或可疑交易进行事后分析

**如何提问：**

> "0x... on Ethereum drained funds from our protocol. Walk me through what happened: who ended up with the money, what the attacker called, and where the exploit entered our contracts."

**Claude 会做什么：**

1. 首先调用 `get_transaction_fund_flow`——按顺序排列的代币与原生资金流以及每个地址的净流量会立刻暴露攻击者的钱包和被抽干的协议地址。
2. 调用 `get_trace_skeleton` 绘制攻击者的调用结构图，而无需加载每个参数。
3. 调用 `search_call_trace` 搜索对协议合约的调用（按地址）以隔离入口点。
4. 对入口点调用 `get_call_trace_node` 获取解码参数，然后调用 `get_subtree_state_changes` 查看该攻击改变了哪些状态。
5. 对攻击者交互过的任何未知合约（helper、代理、已知的漏洞合约）调用 `get_contract_info`。

**您能得到：**

一份以资金为主线的攻击叙事：谁收到了什么、触发抽干的确切函数和参数，以及使其成为可能的状态变化。足够详细以撰写事件报告或开始编写补丁。

***

## 调查一次意外的清算

**如何提问：**

> "My Aave position got liquidated in 0x..., figure out why. I want to know the oracle price at liquidation time and the exact health-factor path."

**Claude 会做什么：**

1. 调用 `trace_transaction` 和 `get_trace_skeleton` 绘制清算调用树。
2. 调用 `search_call_trace` 搜索预言机调用（例如 `latestAnswer`、`getAssetPrice`）以找到清算使用的价格读取。
3. 对每个匹配调用 `get_call_trace_node` 获取解码后的返回值——用于健康因子计算的确切价格。
4. 调用 `get_transaction_fund_flow` 展示扣押了多少抵押品、偿还的债务，以及清算人的奖励。
5. 可选对清算子树调用 `get_subtree_events` 按顺序查看 `LiquidationCall` 和 `Transfer` 事件。

**您能得到：**

使用的预言机价格、清算人的利润、精确的抵押品和债务金额，以及（如适用）使您健康因子跌破 1 的区块或交易。一个完整的 "我为何被清算" 答案。

***

## 审计一笔 1inch/聚合器 swap 收益低于预期的问题

**如何提问：**

> "0x... was a 1inch swap where I got significantly less USDC than the quote. Which pool or hop gave the bad price?"

**Claude 会做什么：**

1. 调用 `get_trace_stats`——聚合器路径可能很深，涉及许多 pool hop。
2. 调用 `get_trace_skeleton` 按顺序查看 pool 调用序列。
3. 调用 `search_call_trace` 搜索 `swap`、`exactInput` 或 router 的 pool 交互 selector，把每一跳都拉出来。
4. 对每一跳调用 `get_call_trace_node` 获取解码后的 `amountIn`/`amountOut` 值。
5. 调用 `get_transaction_fund_flow` 确认最终净收到的金额和任何意外的转账（手续费、返利）。

**您能得到：**

按跳分解的路径上每一跳的输入和输出金额，标出执行低于预期的 pool。适用于测量滑点、比较路径或捕捉过时报价问题。

***

## 使用修复方案重新模拟一笔失败交易

**如何提问：**

> "Transaction 0x... failed with 'ERC20: transfer amount exceeds balance'. Re-simulate it but override my USDC balance to 10,000 USDC to confirm that's the only issue."

**Claude 会做什么：**

1. 使用原交易哈希调用 `resimulate_transaction`，并附加一个将您的代币余额设置为 10,000 USDC 的状态覆盖。
2. 如果模拟成功，确认根本原因是余额不足。
3. 调用 `get_simulation_call_trace` 验证执行路径现在能无错误完成。
4. 可选调用 `get_simulation_asset_transfers` 展示如果成功交易会做什么。

**您能得到：**

确认修复是否解决问题，无需部署任何东西或消耗 gas。状态覆盖让您可以针对真实的 Mainnet 状态即时测试假设——余额不足、错误的授权、错误的所有权。

***

## 理解一笔交易做了什么

**如何提问：**

> "Walk me through everything that happened in transaction 0x... on Ethereum, every internal call, who called who, and what changed."

**Claude 会做什么：**

1. 调用 `trace_transaction` 获取顶层摘要：方法名、发送者、接收者、gas 消耗和状态。
2. 调用 `get_simulation_call_trace` 获取完整的内部调用树——每次嵌套调用及其解码后的函数名、输入、输出和每次调用的 gas。
3. 调用 `get_simulation_events` 按顺序列出所有发出的事件。
4. 调用 `get_simulation_state_changes` 展示每个变化的存储槽和余额。

**您能得到：**

一份完整、人类可读的交易重构。适用于审计不熟悉的协议交互、理解 MEV 活动，或验证复杂的多合约调用是否完全按您预期执行。

***

## 检查一个智能合约

**如何提问：**

> "What contract is deployed at 0xdAC17F958D2ee523a2206206994597C13D831ec7 on Ethereum?"

**Claude 会做什么：**

1. 使用该地址和 Ethereum 的网络 ID 调用 `get_contract_info`。

**您能得到：**

合约名称（Tether USD）、代币标准（ERC-20）、编译器版本、EVM 版本、源代码语言、创建区块、部署者地址、创建交易哈希以及完整的 ABI。Claude 随后可以使用该 ABI 帮助您为模拟编码 calldata 或构建交易。

***

## 在 Virtual Environment 上发送冒充交易并进行追踪

**如何提问：**

> "On my Virtual Environment, send a transaction from the Uniswap V2 deployer 0x1a9C8182C09F50C8318d769245beA52c32BE35BC to the USDC contract 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 calling the `transfer` function to send 1000 USDC to my wallet. Then trace the execution."

**Claude 会做什么：**

1. 在激活的 Virtual Environment 上调用 `send_vnet_transaction`，以部署者作为 `from`、USDC 作为 `to`，并传入 ABI 编码的 `transfer` calldata。发送者被冒充——无需私钥。
2. 调用 `get_vnet_transactions` 获取已执行交易的 `operation_id`。
3. 调用 `trace_vnet_transaction` 获取解码后的执行摘要——合约名、函数名、解码后的输入参数和输出。
4. 可选调用 `get_vnet_simulation_events` 和 `get_vnet_simulation_state_changes` 获取更深入的细节。

**您能得到：**

确认交易已执行、显示 `transfer` 调用成功的解码追踪，以及发出的事件（以您的钱包为接收方的 Transfer 事件）。

***

## 在 Virtual Environment 上测试多步骤合约交互

**如何提问：**

> "On my Virtual Environment, run the full approval and swap flow: first approve the Uniswap router to spend 1000 USDC from my wallet, then execute the swap. Show me my balances before and after."

**Claude 会做什么：**

1. 在激活的 Virtual Environment 上调用 `send_vnet_transaction` 提交 `approve` 交易，冒充您的钱包——无需私钥。
2. 再次调用 `send_vnet_transaction` 传入 swap calldata。
3. 对每笔交易调用 `get_vnet_simulation_asset_changes` 展示每一步的代币变动。
4. 在最后一步之后调用 `get_vnet_simulation_balance_changes` 展示净余额影响。

**您能得到：**

每笔交易成功的分步确认、每一步的代币转账，以及您最终的净余额变化。这就是完整的部署前测试循环——在触碰真实资金之前，针对 fork 的 Mainnet 状态运行任意交易序列。

***

## 分析 gas 使用以进行优化

**如何提问：**

> "Simulate this transaction and show me a gas breakdown so I can find the most expensive function calls: \[paste calldata or describe the transaction]"

**Claude 会做什么：**

1. 使用您的交易参数调用 `simulate_transaction`。
2. 调用 `get_simulation_gas_breakdown` 获取每次调用的 gas 消耗，包括固有 gas 和退款。
3. 调用 `get_simulation_call_trace` 将 gas 成本映射到执行树中的特定函数调用。

**您能得到：**

按消耗排名的 gas 最贵操作列表，映射到具体函数调用。用它来识别合约逻辑中需要优化的部分。

<Note>
  使用 `get_simulation_generated_access_list` 生成 EIP-2930 access list，可通过预先声明交易将访问的存储槽和地址来降低 gas 成本。
</Note>

***

## Fork Virtual Environment 用于并行测试

**如何提问：**

> "Fork my current Virtual Environment so I can test a different approach without losing the current state."

**Claude 会做什么：**

1. 调用 `list_vnets` 找到您当前的 Virtual Environment，如需要则调用 `set_active_vnet`。
2. 调用 `fork_vnet` 创建一个保留所有状态（已部署合约、余额和交易历史）的新 Virtual Environment。fork 自动设为激活。
3. 返回新的 Virtual Environment 详情，包含全新的 RPC URL。

**您能得到：**

两个共享同一起始状态的独立 Virtual Environment。您可以在每个中测试不同的合约变更或交易序列而互不干扰——就像 git 的分支，但用于区块链状态。

***

## 快照、测试与回滚用于压力测试

**如何提问：**

> "On my Virtual Environment, snapshot the current state, then simulate a liquidation on Aave with different oracle prices. Revert to the snapshot between each attempt so I can compare outcomes."

**Claude 会做什么：**

1. 调用 `snapshot_vnet` 保存当前 Virtual Environment 状态，获得快照 ID。
2. 调用 `set_storage_at` 将预言机价格覆盖为特定值。
3. 调用 `send_vnet_transaction` 触发清算。
4. 调用 `get_vnet_simulation_balance_changes` 和 `get_vnet_simulation_asset_changes` 捕获结果。
5. 调用 `revert_vnet` 将 Virtual Environment 恢复到快照状态（快照被消耗）。
6. 再次调用 `snapshot_vnet` 用于下一次迭代，设置不同的预言机价格并重复。

**您能得到：**

在不同价格情景下并排比较清算结果，所有测试都针对真实 fork 状态运行，无需部署任何东西或影响其他测试。

***

## 为测试设置 ERC-20 余额

**如何提问：**

> "On my Virtual Environment, give my wallet 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 a balance of 10,000 USDC and 5 WETH so I can test a swap."

**Claude 会做什么：**

1. 调用 `set_erc20_balance` 传入 USDC 代币地址、您的钱包和所需金额。
2. 再次调用 `set_erc20_balance` 传入 WETH 代币地址和金额。
3. 可选通过 `balanceOf` 调用使用 `vnet_call` 验证余额已正确设置。

**您能得到：**

您的钱包已注入精确的代币金额，准备进行测试。这比手动计算存储槽更简单——`set_erc20_balance` 自动处理代币的存储布局。

***

## 时间旅行以测试 timelock 和 vesting

**如何提问：**

> "On my Virtual Environment, advance the clock by 7 days to test whether my timelock contract unlocks correctly."

**Claude 会做什么：**

1. 调用 `increase_time` 传入 604800 秒（7 天）以推进 Virtual Environment 的时钟。
2. 调用 `mine_block` 将时间变化提交到新区块。
3. 调用 `vnet_call` 读取 timelock 合约的状态（例如 `isUnlocked()` 或 `releaseTime()`）。
4. 可选调用 `send_vnet_transaction` 执行解锁并验证是否成功。

**您能得到：**

在时间跳跃后 timelock 是否可解锁的确认，无需等待真实的 7 天。可用于任何时间相关逻辑：vesting 计划、治理投票期、利息累积或冷却窗口。
