Optimism
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.
Response Example (Default Tracer)
Response with callTracer
The callTracer produces a hierarchical representation of all calls made during execution:
Available Tracers
Geth provides several built-in tracers:
- Default tracer: Provides detailed opcode-level execution logs
- callTracer: Focuses on call hierarchy and less on individual operations
- prestateTracer: Shows the state before execution
- 4byteTracer: Collects statistics about method calls
- noopTracer: Minimalistic tracer that does nothing
- 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, ordisableStorageoptions for large contracts - The
callTracerprovides 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
toaddress and provide initialization bytecode indata - 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
- debug_traceTransaction - Trace an existing transaction
- debug_traceBlock - Trace all transactions in a block
- debug_traceBlockByNumber - Trace transactions in a block by number
- debug_traceBlockByHash - Trace transactions in a block by hash
- trace_call - Alternative tracing API with different output format
- eth_call - Execute a call without tracing information
- debug_storageRangeAt - Inspect contract storage directly
Parameters
Transaction call object (JSON)
Block number in hex format or tag ('latest', 'earliest', 'pending', 'safe', 'finalized') or block hash
Trace options to configure the debugging output (JSON)