Skip to main content

debug_traceTransaction API Guide

This guide explains the debug_traceTransaction RPC method implemented in Forest, which follows the Geth debug namespace format.

Overview

debug_traceTransaction re-executes an existing on-chain transaction and returns detailed execution traces. Unlike trace_call (which simulates a call), this method traces a transaction that has already been mined. It's useful for:

  • Debugging failed or unexpected transactions
  • Analyzing the full execution trace of a historical transaction
  • Inspecting pre/post state changes caused by a specific transaction
  • Understanding nested call hierarchies in complex transactions

Request Format

{
"jsonrpc": "2.0",
"id": 1,
"method": "debug_traceTransaction",
"params": [
"0x...", // Transaction hash
{
"tracer": "prestateTracer", // Tracer type
"tracerConfig": { "diffMode": false } // Tracer-specific config (optional)
}
]
}

Supported Tracers

TracerDescription
callTracerCall hierarchy with inputs, outputs, gas used, and nested calls
flatCallTracerFlattened list of all calls (no nesting)
prestateTracerPre-execution state snapshot of all touched accounts

Tracer Configuration

prestateTracer Config

OptionTypeDefaultDescription
diffModeboolfalseWhen true, returns both pre and post state

callTracer Config

OptionTypeDefaultDescription
onlyTopCallboolfalseWhen true, only trace top call

Response Formats

prestateTracer (Default Mode)

Returns the pre-execution state of every account touched during the transaction. Each account includes only the fields that are relevant (empty fields are omitted).

{
"result": {
"0xcontract...": {
"balance": "0xde0b6b3a7640000",
"code": "0x6080...",
"nonce": "0x1",
"storage": {
"0x0000...0000": "0x0000...002a"
}
},
"0xsender...": {
"balance": "0x72c3a2e371dcc225",
"nonce": "0x1e"
}
}
}

Fields per account:

FieldTypeDescription
balancehex stringAccount balance before the transaction
noncehex stringAccount nonce before the transaction
codehex stringContract bytecode (omitted for EOAs)
storagemap (hex -> hex)Storage slots that were changed by the transaction

prestateTracer (Diff Mode)

When diffMode: true, returns separate pre and post objects showing the state before and after the transaction.

{
"result": {
"pre": {
"0xcontract...": {
"balance": "0xde0b6b3a7640000",
"nonce": "0x1",
"storage": {
"0x0000...0000": "0x0000...002a"
}
},
"0xsender...": {
"balance": "0x72c3a2e371dcc225",
"nonce": "0x1e"
}
},
"post": {
"0xcontract...": {
"storage": {
"0x0000...0000": "0x0000...007b"
}
},
"0xsender...": {
"balance": "0x72c3a1fb5a411da3",
"nonce": "0x1f"
}
}
}
}

Diff mode behavior:

  • pre contains the state before execution for all touched accounts
  • post contains only the fields that changed after execution
  • Accounts that were deleted appear in pre but not in post
  • Accounts that were created appear in post but not in pre
  • Unchanged accounts are omitted from both pre and post
  • Zero-value storage entries are stripped from post

callTracer

Returns the call hierarchy as a nested tree of call frames.

{
"result": {
"type": "CALL",
"from": "0xsender...",
"to": "0xcontract...",
"value": "0x0",
"gas": "0x...",
"gasUsed": "0x...",
"input": "0x4018d9aa...",
"output": "0x...",
"calls": [
{
"type": "CALL",
"from": "0xcontract...",
"to": "0xcontract...",
"value": "0x0",
"gas": "0x...",
"gasUsed": "0x...",
"input": "0x...",
"output": "0x..."
}
]
}
}

flatCallTracer

Returns a flat list of all call frames (equivalent to Parity-style trace).

{
"result": [
{
"type": "call",
"subtraces": 1,
"traceAddress": [],
"action": {
"callType": "call",
"from": "0x...",
"to": "0x...",
"gas": "0x...",
"value": "0x0",
"input": "0x..."
},
"result": {
"gasUsed": "0x...",
"output": "0x..."
}
}
]
}

Using debug_traceTransaction with Forest

Prerequisites

  • A running Forest node — follow the Getting Started guide to start and sync.
  • A transaction hash from a mined transaction on the synced network.

Forest RPC endpoint: http://localhost:2345/rpc/v1

Deployed Contracts

A Tracer contract is pre-deployed on Calibnet and Mainnet for testing. You can send transactions to these contracts and then trace them.

NetworkContract Address
Calibnet0x73a43475aa2ccb14246613708b399f4b2ba546c7
Mainnet0x9BB686Ba6a50D1CF670a98f522a59555d4977fb2

Note: To trace a transaction, the Forest node must have the state data for the epoch containing that transaction. Recent transactions on a synced node should always be traceable.

Sending a Test Transaction

To generate a transaction for tracing, send a transaction using cast:

cast send $CONTRACT "setX(uint256)" 123 \
--rpc-url http://localhost:2345/rpc/v1 \
--private-key <YOUR_PRIVATE_KEY>

# Output:
# transactionHash: 0x90aa2b46...

Save the transaction hash for use in the tracing examples below.

Example curl Requests

Before running the examples, set the following environment variables:

export FOREST_RPC_URL="http://localhost:2345/rpc/v1"
export TX_HASH="0xYOUR_TRANSACTION_HASH"

1. Prestate Trace - Default Mode

Returns the pre-execution state of all accounts touched by the transaction.

curl -s -X POST "$FOREST_RPC_URL" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "debug_traceTransaction",
"params": [
"'$TX_HASH'",
{"tracer": "prestateTracer"}
]
}' | jq '.'

2. Prestate Trace - Diff Mode

Returns both pre and post state, showing exactly what changed.

curl -s -X POST "$FOREST_RPC_URL" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "debug_traceTransaction",
"params": [
"'$TX_HASH'",
{"tracer": "prestateTracer", "tracerConfig": {"diffMode": true}}
]
}' | jq '.'

3. Call Trace

Returns the call hierarchy showing nested calls, gas usage, and return values.

curl -s -X POST "$FOREST_RPC_URL" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "debug_traceTransaction",
"params": [
"'$TX_HASH'",
{"tracer": "callTracer"}
]
}' | jq '.'

4. Flat Call Trace

Returns a flattened list of all calls (Parity-style trace format).

curl -s -X POST "$FOREST_RPC_URL" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "debug_traceTransaction",
"params": [
"'$TX_HASH'",
{"tracer": "flatCallTracer"}
]
}' | jq '.'

Troubleshooting

Common Issues

  1. "message not found in tipset": The transaction hash may not exist on the chain, or the node may not have synced the epoch containing this transaction.
  2. "replay for prestate failed": The node does not have the state data required to re-execute the transaction. Ensure the node is synced past the epoch containing the transaction.
  3. Empty storage in prestate: The contract may not be an EVM actor, or no storage slots were modified by the transaction.
  4. Extra addresses in response: Forest may include Filecoin ID addresses (e.g., 0xff00...) alongside EVM addresses. This is expected behavior due to Filecoin's dual address representation.

Debug Tips

# Look up a transaction by hash
curl -s -X POST "$FOREST_RPC_URL" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByHash","params":["'$TX_HASH'"]}' \
| jq '.'

# Get transaction receipt (confirms it was mined)
curl -s -X POST "$FOREST_RPC_URL" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["'$TX_HASH'"]}' \
| jq '.result.status'

Filecoin-Specific Behavior

Forest's debug_traceTransaction implementation has some differences from standard Ethereum implementations due to Filecoin's architecture:

AspectForest (Filecoin)Geth (Ethereum)
ID addressesMay include 0xff00... Filecoin ID addressesOnly EVM addresses
CoinbaseNot included (gas handled at protocol level)Included as 0x0000...0000
Per-message stateRe-executes all prior messages in the tipsetRe-executes all prior txns in block
Storage modelEVM storage via KAMT (Key-Address-Merkle-Tree)Standard Merkle Patricia Trie

Official Resources