Getting started with TheRPC
Ethereum/Debug API/debug_traceCall

debug_traceCall

The debug_traceCall method executes a call to a contract and returns a detailed trace of its execution at the opcode level, without creating a transaction on the blockchain. This provides the deepest possible visibility into how the Ethereum Virtual Machine (EVM) processes contract calls, making it an essential tool for debugging and detailed analysis.

Use Cases

  • Debug complex smart contract functions with step-by-step opcode execution
  • Analyze memory and storage operations during contract execution
  • Identify gas optimization opportunities by examining opcode-level gas costs
  • Perform detailed security analysis of contract execution paths
  • Test contract behavior under different input conditions
  • Investigate function reverts and execution failures with full context
  • Understand complex multi-contract interactions at the bytecode level
  • Verify the exact execution flow of contract logic
  • Detect stack overflows and other low-level execution issues
  • Analyze how contracts manipulate memory and storage

Method Details

This method simulates a contract call and provides detailed execution information at the opcode level.

Parameters:

Transaction call object

Address the transaction is sent from

Address the transaction is directed to

Gas provided for the transaction execution (hex)

Gas price in wei (hex)

Value transferred in wei (hex)

Contract method call data (function selector and encoded parameters)

Block number in hex format or tag ('latest', 'earliest', 'pending', 'safe', 'finalized') or block hash

Trace options to configure the debugging output

Setting this to true disables storage capture

Setting this to true disables memory capture

Setting this to true disables stack capture

Use a custom tracer (available: callTracer, prestateTracer, etc.)

Overrides the default timeout for JavaScript-based tracing

Returns:

Trace object with detailed execution information

Gas used during the call

Whether the call failed

The returned data from the call

Array of structured EVM operation logs

Program counter position

The opcode executed

Remaining gas

Gas cost for this opcode

Call depth

EVM memory contents (if not disabled)

EVM stack contents (if not disabled)

Storage changes (if not disabled)

Response Example (Default Tracer)

{
	"jsonrpc": "2.0",
	"id": 1,
	"result": {
		"gas": 26848,
		"failed": false,
		"returnValue": "0x000000000000000000000000000000000000000000000000000000000001e240",
		"structLogs": [
			{
				"pc": 0,
				"op": "PUSH1",
				"gas": 190129,
				"gasCost": 3,
				"depth": 1,
				"stack": [],
				"memory": [],
				"storage": {}
			},
			{
				"pc": 2,
				"op": "MSTORE",
				"gas": 190126,
				"gasCost": 12,
				"depth": 1,
				"stack": ["0x60", "0x40"],
				"memory": [
					"0000000000000000000000000000000000000000000000000000000000000000",
					"0000000000000000000000000000000000000000000000000000000000000000"
				],
				"storage": {}
			}
			// ... more operations
		]
	}
}

Response with callTracer

The callTracer produces a hierarchical representation of all calls made during execution:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "type": "CALL",
    "from": "0xd7dad5d1413e8c08f2d92d5bd905bed62d9e2400",
    "to": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
    "value": "0x0",
    "gas": "0x2cb9e",
    "gasUsed": "0x68c5",
    "input": "0x70a08231000000000000000000000000d7dad5d1413e8c08f2d92d5bd905bed62d9e2400",
    "output": "0x000000000000000000000000000000000000000000000000000000000001e240",
    "calls": [
      {
        "type": "STATICCALL",
        "from": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
        "to": "0x000000000000000000000000000000000000000a",
        "gas": "0x26b2f",
        "gasUsed": "0xd5",
        "input": "0x1c0e9c09",
        "output": "0x0000000000000000000000000000000000000000000000000000000000000001"
      }
    ]
  }
}

Available Tracers

Geth provides several built-in tracers:

  1. Default tracer: Provides detailed opcode-level execution logs
  2. callTracer: Focuses on call hierarchy and less on individual operations
  3. prestateTracer: Shows the state before execution
  4. 4byteTracer: Collects statistics about method calls
  5. noopTracer: Minimalistic tracer that does nothing
  6. opCountTracer: Counts opcode occurrences

Additionally, you can use JavaScript-based custom tracers for specialized analysis.

Trace Options

The options parameter lets you configure the tracing:

  • disableStorage: Reduces output size by removing storage details
  • disableMemory: Reduces output size by removing memory details
  • disableStack: Reduces output size by removing stack details
  • tracer: Specifies a specialized tracer to use
  • tracerConfig: Additional configuration for custom tracers (not shown)
  • timeout: Sets timeout for JavaScript tracers (e.g., "10s")

EVM Opcodes

The default tracer returns every opcode execution in the VM. Common opcodes you'll see:

  • PUSH1, PUSH2, etc.: Push values to the stack
  • POP: Remove item from stack
  • ADD, MUL, SUB, DIV: Arithmetic operations
  • SLOAD, SSTORE: Storage load and store
  • MLOAD, MSTORE, MSTORE8: Memory operations
  • CALL, STATICCALL, DELEGATECALL: External calls
  • JUMP, JUMPI: Control flow
  • RETURN, REVERT: Terminate execution

Understanding structLogs

The structLogs array contains one entry for each opcode executed:

  • pc: Program counter - position in the bytecode
  • op: The operation being executed
  • gas: Remaining gas at this point
  • gasCost: Cost of this specific operation
  • depth: Call depth (1 for top level, increases for each call)
  • stack: Current values on the EVM stack
  • memory: Current state of memory
  • storage: Storage locations accessed during this operation

Performance Considerations

  • Opcode-level tracing produces extremely large outputs for complex contracts
  • Consider using the disableMemory, disableStack, or disableStorage options for large contracts
  • The callTracer provides a much more compact output focusing just on the call structure
  • For complex contracts, response times can be significant
  • Set appropriate timeouts for JavaScript tracers
  • Specialized tracers (like callTracer) have much better performance for specific use cases
  • Consider limiting the scope of what you trace (function execution vs. entire contract)
  • Tracing against archive nodes for historical states may take longer

Important Notes

  • This method requires debug APIs to be enabled on the node (--http.api=eth,debug,net,web3)
  • Not all Ethereum clients support the debug_traceCall method or have the same behavior
  • The response size can be extremely large for complex contracts
  • For contract creations, use a null to address and provide initialization bytecode in data
  • Output format differs between tracers and may change between client versions
  • Some opcodes might not be accurately represented in older client versions
  • Delegatecall executions maintain the caller's context, which can be confusing in traces
  • Memory and stack values are represented in hex and may need decoding to be human-readable
  • Reverted executions will trace up to the point of reversion
  • For production systems, using this method may significantly increase load on the node

See also

Help Us Get Better!
Share this page and help us create an even better product for you.