MCP Server
Examples

Examples

These walkthroughs show how Claude uses Tenderly MCP tools to complete real development tasks. You don’t need to call tools by name — just describe what you want and Claude handles the rest.

The examples are grouped roughly by activity:

  • Setup & pre-flight — spinning up environments, funding wallets, checking transactions before you sign.
  • Debugging & post-mortem — figuring out why a transaction failed, who took funds, or why a swap returned less than expected. The advanced trace navigation tools shine here.
  • VNet workflows — impersonation, multi-step testing, snapshots, time-travel, token balance overrides.
  • Optimization & inspection — gas breakdowns, contract metadata.

Create a Virtual TestNet and fund a wallet

What to ask:

“Create a Virtual TestNet forked from Ethereum mainnet and fund my wallet 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 with 100 ETH.”

What Claude does:

  1. Calls list_projects to find your projects, then set_active_project to select one.
  2. Calls get_networks to find the Ethereum mainnet network ID.
  3. Calls create_vnet with the network ID, creating a forked environment. The new VNet is automatically set as active.
  4. Calls fund_account with your wallet address, setting the balance to 100 ETH in hex wei. Operates on the active VNet automatically.
  5. Returns the VNet details including Admin RPC and Public RPC URLs, ready for use in Hardhat, Foundry, or any Web3 library.

What you get back:

A running Virtual TestNet forked from latest mainnet state, your wallet funded, and RPC URLs you can drop into your development framework config.


Simulate a Uniswap swap

What to ask:

“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.”

What Claude does:

  1. Calls simulate_transaction with the Uniswap V3 router address, your sender address, the swap calldata, and 1 ETH as value.
  2. The simulation runs against current mainnet state and returns: success/revert status, gas used, and decoded method name.
  3. Calls get_simulation_asset_transfers to show all token movements — the ETH going in and USDC coming out.
  4. Calls get_simulation_balance_changes to show the net impact on your balances with USD values.

What you get back:

The exact USDC output, gas cost, and a breakdown of every asset transfer. If the swap would revert (e.g., slippage too high), you get the decoded revert reason.


Pre-flight check a transaction before sending

What to ask:

“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.”

What Claude does:

  1. Calls simulate_transaction with your wallet as sender, the token contract as recipient, and the approve calldata.
  2. Calls get_simulation_exposure_changes to show every approval and allowance change — which spender gets access to what, and how much.
  3. Calls get_simulation_state_changes to show the exact storage slots modified.

What you get back:

The exact approval being granted (spender address, token, amount), the storage diff confirming the allowance slot changed, and whether the transaction would succeed. Useful any time you’re interacting with an unfamiliar contract or want to verify calldata before signing.


Debug a failed on-chain transaction

What to ask:

“Why did transaction 0x6c5df5a1e6b34e2432ae19706e38a84239495cdbf40c2a9d4d79806443c4aa0d revert on Ethereum?”

What Claude does:

  1. Calls trace_transaction with the tx hash. Returns the status (false = reverted), gas used, decoded method name, and error message.
  2. Calls get_simulation_call_trace to get the full internal call tree — every function call, with decoded names, inputs, outputs, and which specific call failed.
  3. Calls get_simulation_events to see what events were emitted before the revert point.
  4. Optionally calls get_simulation_state_changes to see what state was modified up to the failure.

What you get back:

A clear explanation of exactly which internal call failed, the decoded revert reason (e.g., "ERC20: transfer amount exceeds balance"), and the full call trace so you can see the execution path leading up to the failure.


Find the root cause of a revert in a deeply nested transaction

What to ask:

“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.”

What Claude does:

  1. Calls trace_transaction for the top-level summary and confirms the revert.
  2. Calls find_failures to list every failing call in the transaction — not just the outermost one. This surfaces both the originating revert and any wrapping require/try-catch failures.
  3. Calls get_error_path to return the blame chain from the root call down to the deepest failing call, with decoded inputs and outputs at each level.
  4. If any node still has omitted children, calls get_call_trace_node on the specific position to expand it.

What you get back:

The exact contract, function, and decoded revert reason at the deepest failure, plus the full chain of callers that led there. Much faster than paging through a 200-call get_simulation_call_trace output.


Navigate a very large trace

What to ask:

“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.”

What Claude does:

  1. Calls get_trace_stats to report total calls, max depth, error count, and unique contracts — a quick size check that decides the strategy.
  2. Calls get_trace_skeleton to get a compressed call tree: function name, contract, depth, and error flag per node, without decoded args.
  3. Identifies the interesting subtree (a failing branch, a specific protocol, or a suspicious contract) using absolute_position values from the skeleton.
  4. Calls get_call_trace_node to expand that subtree with full decoded inputs and outputs.
  5. Optionally calls get_subtree_events and get_subtree_state_changes to see only the events and storage diffs from that subtree.

What you get back:

A map of the transaction’s structure, then full detail on just the part you care about — without loading thousands of calls into context.


Search a trace for a specific contract or function

What to ask:

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

What Claude does:

  1. Calls search_call_trace with the USDC address and transferFrom as filters — returning only matching calls with their decoded inputs, outputs, and absolute positions.
  2. For any match that’s interesting, calls get_call_trace_node to fetch the full nested context around it.

What you get back:

A targeted list of matching calls instead of the full trace. Useful for answering “did X happen” questions on large transactions, and for auditing whether a known-risky selector was invoked.


Follow the money through a transaction

What to ask:

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

What Claude does:

  1. Calls get_transaction_fund_flow with the tx hash. Returns ordered token and native transfers, each with from/to addresses and USD values, plus a net flow per address.
  2. Optionally calls get_contract_info on any unfamiliar address to identify it (protocol router, pool, treasury, etc.).

What you get back:

A chronological money map of the transaction and a per-address net flow — ideal for understanding MEV bundles, unfamiliar DeFi interactions, or verifying that a multi-hop swap moved funds as expected. On-chain transactions only.


Debug a failed Safe multisig batch execution

What to ask:

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

What Claude does:

  1. Calls trace_transaction to confirm the revert and get the top-level method (execTransaction or multiSend).
  2. Calls get_trace_stats — Safe batches explode into large traces quickly, so the stats decide the next step.
  3. Calls find_failures — because multiSend often reverts the whole batch on any sub-call failure, this is the fastest way to see which of the 12 operations blew up, not just the outer Safe revert.
  4. Calls get_error_path on the failing sub-call for the full decoded input/output chain at each level.
  5. Optionally calls get_call_trace_node if any relevant node was truncated.

What you get back:

The exact sub-call inside the batch that failed, with the decoded target, function, arguments, and revert reason — rather than a generic “GS013” Safe error with no context.


Post-mortem an exploit or suspicious transaction

What to ask:

“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.”

What Claude does:

  1. Calls get_transaction_fund_flow first — the ordered token and native flows plus per-address net flow surface the attacker’s wallet and the drained protocol addresses immediately.
  2. Calls get_trace_skeleton to map the attacker’s call structure without loading every argument.
  3. Calls search_call_trace for calls into the protocol’s contracts (by address) to isolate the entry point.
  4. Calls get_call_trace_node on the entry point for decoded args, then get_subtree_state_changes to see exactly what state the exploit mutated.
  5. Calls get_contract_info on any unknown contracts the attacker interacted with (helpers, proxies, known exploit contracts).

What you get back:

A money-first narrative of the exploit: who received what, the exact function and arguments that triggered the drain, and the state changes that made it possible. Enough detail to write an incident report or start a patch.


Investigate an unexpected liquidation

What to ask:

“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.”

What Claude does:

  1. Calls trace_transaction and get_trace_skeleton to map the liquidation call tree.
  2. Calls search_call_trace for oracle calls (e.g., latestAnswer, getAssetPrice) to find the price reads the liquidation used.
  3. Calls get_call_trace_node on each match for the decoded return values — the exact price feeding the health-factor math.
  4. Calls get_transaction_fund_flow to show how much collateral was seized, the debt repaid, and the liquidator’s bonus.
  5. Optionally calls get_subtree_events on the liquidation subtree for LiquidationCall and Transfer events in order.

What you get back:

The oracle prices used, the liquidator’s profit, the exact collateral and debt amounts, and — if applicable — the block or transaction that moved your health factor below 1. A complete “why did I get liquidated” answer.


Audit a 1inch / aggregator swap that returned less than expected

What to ask:

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

What Claude does:

  1. Calls get_trace_stats — aggregator routes can be deep with many pool hops.
  2. Calls get_trace_skeleton to see the sequence of pool calls in order.
  3. Calls search_call_trace for swap, exactInput, or the router’s pool-interaction selectors, pulling out each hop.
  4. Calls get_call_trace_node on each hop for decoded amountIn / amountOut values.
  5. Calls get_transaction_fund_flow to confirm the final net received and any unexpected transfers (fees, rebates).

What you get back:

A per-hop breakdown of input and output amounts across the route, with the pool that had worse-than-expected execution called out. Useful for measuring slippage, comparing routes, or catching stale-quote issues.


Re-simulate a failed transaction with a fix

What to ask:

“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.”

What Claude does:

  1. Calls resimulate_transaction with the original tx hash and a state override setting your token balance to 10,000 USDC.
  2. If the simulation succeeds, confirms the root cause was insufficient balance.
  3. Calls get_simulation_call_trace to verify the execution path now completes without error.
  4. Optionally calls get_simulation_asset_transfers to show what the transaction would have done if it had succeeded.

What you get back:

Confirmation of whether the fix resolves the issue, without deploying anything or spending gas. State overrides let you test assumptions — insufficient balance, wrong allowance, incorrect ownership — instantly, against real mainnet state.


Understand what a transaction did

What to ask:

“Walk me through everything that happened in transaction 0x… on Ethereum — every internal call, who called who, and what changed.”

What Claude does:

  1. Calls trace_transaction for a top-level summary: method name, sender, recipient, gas used, and status.
  2. Calls get_simulation_call_trace to get the full internal call tree — every nested call with decoded function names, inputs, outputs, and per-call gas.
  3. Calls get_simulation_events to list all events emitted in order.
  4. Calls get_simulation_state_changes to show every storage slot and balance that changed.

What you get back:

A complete, human-readable reconstruction of the transaction. Useful for auditing unfamiliar protocol interactions, understanding MEV activity, or verifying that a complex multi-contract call did exactly what you expected.


Inspect a smart contract

What to ask:

“What contract is deployed at 0xdAC17F958D2ee523a2206206994597C13D831ec7 on Ethereum?”

What Claude does:

  1. Calls get_contract_info with the address and Ethereum’s network ID.

What you get back:

The contract name (Tether USD), token standards (ERC-20), compiler version, EVM version, source language, creation block, deployer address, creation transaction hash, and the full ABI. Claude can then use the ABI to help you encode calldata for simulations or build transactions.


Send an impersonated transaction on a VNet and trace it

What to ask:

“On my VNet, 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.”

What Claude does:

  1. Calls send_vnet_transaction on the active VNet with the deployer as from, USDC as to, and the ABI-encoded transfer calldata. The sender is impersonated — no private key needed.
  2. Calls get_vnet_transactions to get the operation_id of the executed transaction.
  3. Calls trace_vnet_transaction to get the decoded execution summary — contract name, function name, decoded input parameters, and output.
  4. Optionally calls get_vnet_simulation_events and get_vnet_simulation_state_changes for deeper details.

What you get back:

Confirmation that the transaction executed, the decoded trace showing the transfer call succeeded, and the events emitted (Transfer event with your wallet as recipient).


Test a multi-step contract interaction on a VNet

What to ask:

“On my VNet, 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.”

What Claude does:

  1. Calls send_vnet_transaction on the active VNet to submit the approve transaction, impersonating your wallet — no private key needed.
  2. Calls send_vnet_transaction again with the swap calldata.
  3. Calls get_vnet_simulation_asset_changes on each transaction to show token movements per step.
  4. Calls get_vnet_simulation_balance_changes after the final step to show the net balance impact.

What you get back:

Step-by-step confirmation that each transaction succeeded, token transfers per step, and your final net balance change. This is the full pre-deployment testing loop — run any sequence of transactions against a forked mainnet state before touching real funds.


Analyze gas usage for optimization

What to ask:

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

What Claude does:

  1. Calls simulate_transaction with your transaction parameters.
  2. Calls get_simulation_gas_breakdown to get per-call gas consumption including intrinsic gas and refunds.
  3. Calls get_simulation_call_trace to map gas costs to specific function calls in the execution tree.

What you get back:

A ranked list of the most gas-expensive operations, mapped to specific function calls. Use this to identify which parts of your contract logic to optimize.

Use get_simulation_generated_access_list to generate an EIP-2930 access list, which can reduce gas costs by pre-declaring which storage slots and addresses the transaction will access.


Fork a VNet for parallel testing

What to ask:

“Fork my current VNet so I can test a different approach without losing the current state.”

What Claude does:

  1. Calls list_vnets to find your current VNet, then set_active_vnet if needed.
  2. Calls fork_vnet, creating a new VNet with all state preserved — deployed contracts, balances, and transaction history. The fork is automatically set as active.
  3. Returns the new VNet details with fresh RPC URLs.

What you get back:

Two independent VNets sharing the same starting state. You can test different contract changes or transaction sequences in each without interference — like branching in git, but for blockchain state.


Snapshot, test, and revert for stress-testing

What to ask:

“On my VNet, 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.”

What Claude does:

  1. Calls snapshot_vnet to save the current VNet state, receiving a snapshot ID.
  2. Calls set_storage_at to override the oracle price to a specific value.
  3. Calls send_vnet_transaction to trigger the liquidation.
  4. Calls get_vnet_simulation_balance_changes and get_vnet_simulation_asset_changes to capture the outcome.
  5. Calls revert_vnet to restore the VNet to the snapshot state (the snapshot is consumed).
  6. Calls snapshot_vnet again for the next iteration, sets a different oracle price, and repeats.

What you get back:

A side-by-side comparison of liquidation outcomes under different price scenarios — all tested against real forked state, without deploying anything or affecting other tests.


Set ERC-20 balances for testing

What to ask:

“On my VNet, give my wallet 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 a balance of 10,000 USDC and 5 WETH so I can test a swap.”

What Claude does:

  1. Calls set_erc20_balance with the USDC token address, your wallet, and the desired amount.
  2. Calls set_erc20_balance again with the WETH token address and amount.
  3. Optionally calls vnet_call with a balanceOf call to verify the balances were set correctly.

What you get back:

Your wallet funded with exact token amounts, ready for testing. This is simpler than calculating storage slots manually — set_erc20_balance handles the token’s storage layout automatically.


Time-travel to test timelocks and vesting

What to ask:

“On my VNet, advance the clock by 7 days to test whether my timelock contract unlocks correctly.”

What Claude does:

  1. Calls increase_time with 604800 seconds (7 days) to advance the VNet clock.
  2. Calls mine_block to commit the time change to a new block.
  3. Calls vnet_call to read the timelock contract’s state (e.g., isUnlocked() or releaseTime()).
  4. Optionally calls send_vnet_transaction to execute the unlock and verify it succeeds.

What you get back:

Confirmation of whether the timelock is unlockable after the time skip, without waiting 7 real days. Use this for any time-dependent logic: vesting schedules, governance voting periods, interest accrual, or cooldown windows.