> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://www.getfoundry.sh/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

## Debugging Transactions

This guide covers replaying and debugging transactions using `cast run`, analyzing traces, and diagnosing common failure patterns.

### Replaying a transaction

Use `cast run` to replay any transaction locally:

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc
```

This executes the transaction against the state at the block where it was mined, showing the full execution trace.

Reproducing that state normally means replaying every earlier transaction in the block. If the node serves an EIP-7928 block access list for the block, `cast run` instead reads the transaction's prestate from the list and executes the transaction directly, which is much faster for transactions late in a busy block. Pass `--no-bal` to force a full replay:

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc --no-bal
```

### Trace verbosity levels

Control trace output with `-v` flags:

| Flag | Shows |
|------|-------|
| (none) | Basic result |
| `-v` | Function calls |
| `-vv` | Calls with parameters |
| `-vvv` | Calls, parameters, and return values |
| `-vvvv` | Full trace including internal calls |
| `-vvvvv` | Full trace with storage changes |

```bash [Detailed trace]
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc -vvvv
```

### Analyzing a failed transaction

:::steps
#### Get the transaction details

```bash
$ cast tx $TX_HASH --rpc-url https://ethereum.reth.rs/rpc
```

#### Check the receipt for failure

```bash
$ cast receipt $TX_HASH --rpc-url https://ethereum.reth.rs/rpc
```

Look for `status: 0` which indicates failure.

#### Replay with traces

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc -vvvv
```

#### Decode the revert reason

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc 2>&1 | grep -A5 "revert"
```
:::

### Decoding revert reasons

`cast run` automatically decodes revert reasons when possible:

```bash
$ cast run 0x1234... --rpc-url https://ethereum.reth.rs/rpc
// @error: Revert: InsufficientBalance(1000000000000000000, 500000000000000000)
```

For custom errors, ensure you have the contract ABI available:

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc --label 0xContractAddress:MyContract
```

### Debugging with quick mode

For faster debugging, use quick mode which skips some validation:

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc --quick
```

### Labeling addresses

Make traces more readable by labeling known addresses:

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc \
    --label 0x6B175474E89094C44Da98b954EeD3CDB5BE3830:DAI \
    --label 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D:UniswapRouter
```

### Debugging in Forge tests

Debug test failures with traces:

```bash
$ forge test --match-test test_Failing -vvvv
```

Use `console.log` for strategic debugging:

```solidity
import {console} from "forge-std/console.sol";

function test_Debug() public {
    console.log("Balance before:", token.balanceOf(alice));
    console.log("Allowance:", token.allowance(alice, address(this)));
    
    vm.prank(alice);
    token.transfer(bob, 100);
    
    console.log("Balance after:", token.balanceOf(alice));
}
```

### Using the debugger

Forge includes an interactive debugger:

```bash
$ forge test --match-test test_Failing --debug
```

Basic controls:

| Key | Action |
|-----|--------|
| `j` / `k` | Step forward / backward |
| `s` / `a` | Move to the next / previous jump |
| `C` / `c` | Move to the next / previous call |
| `g` / `G` | Jump to start / end |
| `q` | Quit |

See [Debugging](/forge/debugging#interactive-debugger) for the full list of key bindings and debugger commands.

### Common failure patterns

#### Out of gas

```
Error: OutOfGas
```

**Diagnosis**: The transaction ran out of gas before completing.

**Solution**: Increase gas limit or optimize the contract.

```bash
# Check actual gas used vs limit
$ cast tx $TX_HASH --rpc-url https://ethereum.reth.rs/rpc | grep -E "gas|gasLimit"
```

#### Revert with no message

```
Error: Revert
```

**Diagnosis**: A `require()` or `revert()` with no message, or an assertion failed.

**Solution**: Check the trace for the exact call that failed:

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc -vvvvv
```

#### Stack too deep

```
Error: Stack too deep
```

**Diagnosis**: Too many local variables in a function.

**Solution**: Reduce local variables or use structs. See the [Stack Too Deep guide](/guides/stack-too-deep) for detailed solutions.

#### Invalid opcode

```
Error: InvalidFEOpcode
```

**Diagnosis**: Hit an `assert()` failure or uninitialized function pointer.

**Solution**: Check for assertion violations in the trace.

### Comparing successful vs failed transactions

Debug by comparing a working transaction with a failed one:

```bash
# Get traces for both
$ cast run $SUCCESS_TX --rpc-url $RPC -vvvv > success.txt
$ cast run $FAILED_TX --rpc-url $RPC -vvvv > failed.txt

# Compare
$ diff success.txt failed.txt
```

### Simulating with modified state

Use Anvil to replay with modifications:

```bash
# Fork at the block before the transaction
$ anvil --fork-url https://ethereum.reth.rs/rpc --fork-block-number $BLOCK_MINUS_ONE
```

Then in a Forge test or script, modify state and replay:

```solidity
function test_DebugWithModifiedState() public {
    // Give the sender more tokens
    deal(address(token), sender, 1000 ether);
    
    // Replay the transaction
    vm.prank(sender);
    target.call(originalCalldata);
}
```

### Gas profiling a transaction

Analyze gas usage breakdown:

```bash
$ cast run $TX_HASH --rpc-url https://ethereum.reth.rs/rpc -vvvv 2>&1 | grep -E "gas:|Gas"
```

### Best practices

| Practice | Description |
|----------|-------------|
| Save failed tx hashes | Keep a log of failed transactions for analysis |
| Use labels | Label known contracts for readable traces |
| Fork at correct block | Always fork at `block - 1` for accurate state |
| Check state changes | Use `-vvvvv` to see storage modifications |
| Compare transactions | Diff successful vs failed tx traces |
