nicofains1

evm-tx-debugger

0
0
# Install this skill:
npx skills add nicofains1/evm-tx-debugger

Or install specific skill: npx add-skill https://github.com/nicofains1/evm-tx-debugger

# Description

Debug failed EVM transactions efficiently using Foundry's cast CLI. Use this skill when analyzing why a blockchain transaction reverted, failed, or produced unexpected results. Covers swaps, NFT mints, bridges, lending protocols, Permit2, and more across 12+ networks.

# SKILL.md


name: evm-tx-debugger
description: Debug failed EVM transactions efficiently using Foundry's cast CLI. Use this skill when analyzing why a blockchain transaction reverted, failed, or produced unexpected results. Covers swaps, NFT mints, bridges, lending protocols, Permit2, and more across 12+ networks.
license: MIT
metadata:
author: nicofains1
version: "1.0.0"


EVM Transaction Debugger

A systematic, efficient approach to diagnose why EVM transactions fail. Uses Foundry's cast CLI and block explorer APIs to identify root causes in seconds, not minutes.

When to Apply

Use this skill when:
- A user reports a failed/reverted transaction
- Investigating why a swap, mint, bridge, or DeFi transaction failed
- Debugging Permit2 signature issues
- Analyzing slippage, deadline, or allowance problems
- Any on-chain transaction that didn't behave as expected

Golden Rules

  1. NEVER use cast run - It simulates the entire transaction and takes minutes. Use targeted commands instead.
  2. Always simulate at block N-1 - Use --block <blockNumber - 1> to reproduce the exact state.
  3. Check the obvious first - 80% of failures are: insufficient balance, slippage, expired deadline, or revoked approval.
  4. No state changes = early revert - If no token transfers occurred, the tx failed in validation.
  5. Gas used == Gas limit = out of gas - If these are equal, the transaction ran out of gas.

Quick Reference

Step Command Purpose
1 cast receipt <hash> Confirm failure, check gas
2 cast tx <hash> Get tx params
3 cast 4byte <selector> Decode function name
4 Blockscout API Decoded params, state changes
5 cast call --block N-1 Reproduce error
6 Context checks Validate prices, nonces, balances

Total time: 10-30 seconds (vs 2-5 minutes with cast run)


Step-by-Step Process

Step 1: Confirm Failure and Check Gas

cast receipt <TX_HASH> --rpc-url <RPC_URL>

Key fields:

Field What to Look For
status 0 = failed, 1 = success
gasUsed If equal to gasLimit → out of gas
logs Empty [] = failed before emitting events
# One-liner
cast receipt <TX_HASH> --rpc-url <RPC_URL> --json | jq '{status, gasUsed, gasLimit: .gas}'

Step 2: Get Transaction Data

cast tx <TX_HASH> --rpc-url <RPC_URL>

Key fields: from, to, input (first 4 bytes = selector), value, blockNumber

cast tx <TX_HASH> --rpc-url <RPC_URL> --json | jq '{from, to, value, blockNumber, input: .input[0:10]}'

Step 3: Decode the Function

cast 4byte <SELECTOR>

Common selectors:

Selector Function Protocol
0x3593564c execute Uniswap Universal Router
0x5ae401dc multicall Uniswap V3
0x12aa3caf swap 1inch v5
0x095ea7b3 approve ERC20
0x23b872dd transferFrom ERC20/ERC721

Complex calldata? If the function is execute, multicall, or similar batch operations, see the ABI Decoder section below.

Step 4: Get Decoded Parameters

# Get decoded transaction details
curl -s "https://<NETWORK>.blockscout.com/api/v2/transactions/<TX_HASH>" | \
  jq '{status, result, revert_reason, method: .decoded_input.method_call, params: .decoded_input.parameters}'

# Check state changes
curl -s "https://<NETWORK>.blockscout.com/api/v2/transactions/<TX_HASH>/state-changes" | \
  jq '.items[] | {address: .address.hash, type, change, token: .token.symbol}'

If only gas was spent (no token transfers): Transaction failed in validation phase.

Step 5: Reproduce the Error

cast call <TO_ADDRESS> \
  --data "<FULL_INPUT_DATA>" \
  --from <FROM_ADDRESS> \
  --value <VALUE> \
  --block $((BLOCK_NUMBER - 1)) \
  --rpc-url <RPC_URL> 2>&1

Step 6: Context-Specific Validation

Token Balance:

cast call <TOKEN> "balanceOf(address)(uint256)" <USER> --block $((BLOCK - 1)) --rpc-url <RPC>

Allowance:

cast call <TOKEN> "allowance(address,address)(uint256)" <OWNER> <SPENDER> --block $((BLOCK - 1)) --rpc-url <RPC>

ETH Balance:

cast balance <ADDRESS> --block $((BLOCK - 1)) --rpc-url <RPC>

Common Failure Patterns

1. Insufficient Slippage (Swaps)

Symptoms: Swap reverts, no token transfers, error mentions "slippage" or "min amount"

Diagnosis:

# Compare minAmountOut with actual market quote using Uniswap V3 Quoter
cast call <QUOTER> \
  "quoteExactInputSingle((address,address,uint256,uint24,uint160))(uint256,uint160,uint32,uint256)" \
  "(<TOKEN_IN>,<TOKEN_OUT>,<AMOUNT_IN>,<FEE>,0)" \
  --block $((BLOCK - 1)) --rpc-url <RPC>

Root cause: Market moved. The minAmountOut was higher than what the market could provide.

2. Expired Deadline

Symptoms: Transaction mined but reverts, error mentions "deadline"

Diagnosis:

cast block <BLOCK> --rpc-url <RPC> --json | jq '.timestamp'
# Compare with deadline parameter: deadline > timestamp = OK

3. Insufficient Balance

Diagnosis:

cast call <TOKEN> "balanceOf(address)(uint256)" <USER> --block $((BLOCK - 1)) --rpc-url <RPC>

4. Insufficient Allowance

Diagnosis:

cast call <TOKEN> "allowance(address,address)(uint256)" <OWNER> <SPENDER> --block $((BLOCK - 1)) --rpc-url <RPC>

5. Permit2 Nonce Already Used

Diagnosis:

PERMIT2="0x000000000022D473030F116dDEE9F6B43aC78BA3"
WORD_POS=$((NONCE >> 8))
cast call $PERMIT2 "nonceBitmap(address,uint256)(uint256)" <USER> $WORD_POS --block $((BLOCK - 1)) --rpc-url <RPC>
# Result of 0 = nonce NOT used

6. Out of Gas

Diagnosis:

cast receipt <TX> --rpc-url <RPC> --json | jq 'if .gasUsed == .gas then "OUT OF GAS" else "Gas OK" end'

7. Contract Paused

Diagnosis:

cast call <CONTRACT> "paused()(bool)" --block $((BLOCK - 1)) --rpc-url <RPC>

ABI Decoder

For complex calldata (multicalls, aggregator routes, batch operations), decode nested calls:

Uniswap Universal Router

# Commands byte mapping:
# 0x00 = V3_SWAP_EXACT_IN, 0x01 = V3_SWAP_EXACT_OUT
# 0x08 = V2_SWAP_EXACT_IN, 0x0b = WRAP_ETH, 0x0c = UNWRAP_ETH

cast pretty-calldata <CALLDATA>
cast calldata-decode "execute(bytes,bytes[],uint256)" <CALLDATA>

Multicall

cast calldata-decode "multicall(uint256,bytes[])" <CALLDATA>
# Then decode each bytes element

1inch / Paraswap

cast calldata-decode "swap(address,(address,address,address,address,uint256,uint256,uint256),bytes,bytes)" <CALLDATA>

Permit2 Batch

cast calldata-decode "permitTransferFrom(((address,uint256),uint256,uint256),(address,uint256)[],address,bytes)" <CALLDATA>

Decode Custom Errors

ERROR_DATA="0x..."
SELECTOR="${ERROR_DATA:0:10}"
cast 4byte $SELECTOR
cast 4byte-decode $SELECTOR "${ERROR_DATA:10}"

Network Reference

Blockscout Domains

Network Domain
Ethereum eth.blockscout.com
Base base.blockscout.com
Optimism optimism.blockscout.com
Arbitrum arbitrum.blockscout.com
Polygon polygon.blockscout.com
Gnosis gnosis.blockscout.com
Scroll scroll.blockscout.com
zkSync Era zksync.blockscout.com
Linea linea.blockscout.com
Blast blast.blockscout.com

Public RPCs

Network RPC URL Chain ID
Ethereum https://eth.llamarpc.com 1
Base https://mainnet.base.org 8453
Optimism https://mainnet.optimism.io 10
Arbitrum https://arb1.arbitrum.io/rpc 42161
Polygon https://polygon-rpc.com 137
BSC https://bsc-dataseed.binance.org 56
Avalanche https://api.avax.network/ext/bc/C/rpc 43114

Key Contract Addresses

Permit2 (all chains): 0x000000000022D473030F116dDEE9F6B43aC78BA3

Uniswap V3 Quoter:
- Ethereum/Optimism/Arbitrum/Polygon: 0x61fFE014bA17989E743c5F6cB21bF9697530B21e
- Base: 0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a


Output Template

## Transaction Debug Summary

**TX Hash:** `0x...`
**Network:** [Network]
**Block:** [block number]
**Status:** FAILED

### Transaction Details
- **From:** `0x...`
- **To:** `0x...` ([Contract Name])
- **Function:** `functionName(params)`
- **Value:** [X ETH]

### Root Cause
[One clear sentence explaining why the transaction failed]

### Evidence
1. [Specific data point with values]
2. [Comparison showing the mismatch]

### Recommendation
[How to avoid this failure in the future]

### Commands Used
```bash
[List exact commands for reproducibility]
---

## Installation

```bash
# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup

# Install jq
brew install jq  # macOS
sudo apt install jq  # Ubuntu

License

MIT - Use freely, attribution appreciated.

# README.md

EVM Transaction Debugger

Debug failed EVM transactions efficiently using Foundry's cast CLI.

Installation

npx skills add nicofains1/evm-tx-debugger

What This Skill Does

Provides AI agents with a systematic 6-step process to diagnose why blockchain transactions fail:

  1. Confirm failure - Check receipt status and gas usage
  2. Get tx data - Extract from, to, calldata, value
  3. Decode function - Identify what was called
  4. Get decoded params - Use Blockscout API for full decoding
  5. Reproduce error - Simulate at previous block
  6. Context checks - Validate balances, allowances, prices, deadlines

Common Failures Covered

  • Insufficient slippage (swaps)
  • Expired deadline
  • Insufficient balance
  • Insufficient allowance
  • Permit2 nonce already used
  • Out of gas
  • Contract paused
  • Access control issues

Networks Supported

Ethereum, Base, Optimism, Arbitrum, Polygon, BSC, Avalanche, Gnosis, Scroll, zkSync Era, Linea, Blast

Example Usage

Give your AI agent a failed transaction:

Debug this failed transaction:
TX: 0xabc123...
Network: Base

The agent will follow the skill's process and return a structured debug summary with root cause and evidence.

Requirements

  • Foundry (cast CLI)
  • jq for JSON parsing

License

MIT

Contributing

Found a new failure pattern? PRs welcome!

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.