This page is a placeholder. All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.
debug Methods
The debug namespace provides 5 debugging and development methods for transaction tracing and block analysis.
Debug methods are not part of the standard JSON-RPC spec and may not be available on all nodes. They are typically only enabled on development and testing nodes.
Overview
Access debug methods directly on the provider:
import { Provider } from '@tevm/voltaire/provider';
import { Keccak256 } from '@tevm/voltaire/Keccak256';
const txHash = Keccak256.from('0x...');
// Trace transaction execution
const trace = await provider.debug_traceTransaction(txHash, {
tracer: 'callTracer'
});
Transaction Tracing
debug_traceTransaction
Trace the execution of a transaction, returning detailed information about each step.
const trace = await provider.debug_traceTransaction(txHash, {
tracer: 'callTracer',
timeout: '10s'
});
// Response<TransactionTrace>
Parameters:
transactionHash: Hash - Transaction to trace
options?: TraceOptions - Tracing configuration
Common Tracers:
callTracer - Call tree with gas and value transfers
prestateTracer - State before transaction execution
4byteTracer - Count of 4-byte function selectors
opcodeTracer - Full opcode-level trace
Example:
import { Keccak256 } from '@tevm/voltaire/Keccak256';
const txHash = Hash('0xabc123...');
// Call tracer - see internal calls
const callTrace = await provider.debug_traceTransaction(txHash, {
tracer: 'callTracer'
});
if (!callTrace.error) {
console.log('Calls:', callTrace.result.calls);
console.log('Gas used:', callTrace.result.gasUsed);
}
// Opcode tracer - detailed execution
const opcodeTrace = await provider.debug_traceTransaction(txHash, {
tracer: 'opcodeTracer',
enableMemory: true,
enableReturnData: true
});
debug_traceBlockByNumber
Trace all transactions in a block by block number.
const traces = await provider.debug_traceBlockByNumber('latest', {
tracer: 'callTracer'
});
// Response<TransactionTrace[]>
Parameters:
blockTag: BlockTag - Block to trace
options?: TraceOptions - Tracing configuration
Example:
// Trace all transactions in latest block
const traces = await provider.debug_traceBlockByNumber('latest', {
tracer: 'callTracer'
});
if (!traces.error) {
traces.result.forEach((trace, i) => {
console.log(`Transaction ${i}:`, trace.result);
});
}
debug_traceBlockByHash
Trace all transactions in a block by block hash.
const traces = await provider.debug_traceBlockByHash(blockHash, {
tracer: 'prestateTracer'
});
// Response<TransactionTrace[]>
Parameters:
blockHash: Hash - Block hash to trace
options?: TraceOptions - Tracing configuration
Example:
import { Keccak256 } from '@tevm/voltaire/Keccak256';
const blockHash = Hash('0xdef456...');
const traces = await provider.debug_traceBlockByHash(blockHash, {
tracer: 'prestateTracer'
});
if (!traces.error) {
console.log('Pre-state:', traces.result[0].result);
}
debug_traceCall
Trace a call without creating a transaction (like eth_call with tracing).
const trace = await provider.debug_traceCall({
from: Address('0x...'),
to: Address('0x...'),
data: Hex('0x...')
}, 'latest', {
tracer: 'callTracer'
});
// Response<TransactionTrace>
Parameters:
callParams: CallParams - Transaction parameters
blockTag: BlockTag - Block to execute against
options?: TraceOptions - Tracing configuration
Example:
import * as Address from '@tevm/voltaire/Address';
import * as Hex from '@tevm/voltaire/Hex';
// Trace a call before submitting
const trace = await provider.debug_traceCall({
from: Address('0x742d35...'),
to: Address('0xcontract...'),
data: Hex('0xa9059cbb...') // transfer(address,uint256)
}, 'latest', {
tracer: 'callTracer'
});
if (!trace.error) {
// Inspect internal calls before submitting transaction
console.log('Will make calls:', trace.result.calls);
}
Block Inspection
debug_getRawBlock
Get the RLP-encoded raw block data.
const rawBlock = await provider.debug_getRawBlock('latest');
// Response<Hex>
Parameters:
blockTag: BlockTag - Block to retrieve
Example:
// Get raw block bytes
const rawBlock = await provider.debug_getRawBlock('latest');
if (!rawBlock.error) {
console.log('RLP-encoded block:', rawBlock.result);
// Can decode with RLP module
}
Trace Options
Common options for tracing methods:
interface TraceOptions {
// Built-in tracer name
tracer?: 'callTracer' | 'prestateTracer' | '4byteTracer' | 'opcodeTracer';
// Custom JavaScript tracer code
tracerConfig?: {
onlyTopCall?: boolean;
withLog?: boolean;
};
// Timeout for tracing operation
timeout?: string; // e.g., '10s', '1m'
// Include memory in trace
enableMemory?: boolean;
// Include return data
enableReturnData?: boolean;
// Disable storage
disableStorage?: boolean;
// Disable stack
disableStack?: boolean;
}
Usage Patterns
Debug Failed Transaction
import { Keccak256 } from '@tevm/voltaire/Keccak256';
async function debugFailedTx(txHash: Keccak256.Keccak256Hash) {
// Get transaction receipt
const receipt = await provider.eth_getTransactionReceipt(txHash);
if (!receipt.error && receipt.result.status === '0x0') {
// Transaction reverted, trace it
const trace = await provider.debug_traceTransaction(txHash, {
tracer: 'callTracer'
});
if (!trace.error) {
console.log('Revert reason:', trace.result.error);
console.log('Failed at:', trace.result.calls);
}
}
}
Analyze Gas Usage
async function analyzeGas(txHash: Keccak256.Keccak256Hash) {
const trace = await provider.debug_traceTransaction(txHash, {
tracer: 'callTracer'
});
if (!trace.error) {
const result = trace.result;
console.log('Total gas:', result.gasUsed);
// Show gas for each call
result.calls?.forEach(call => {
console.log(`${call.type} to ${call.to}: ${call.gasUsed} gas`);
});
}
}
Test Before Sending
async function testTransaction(params: CallParams) {
// Trace the call first
const trace = await provider.debug_traceCall(params, 'latest', {
tracer: 'callTracer'
});
if (!trace.error) {
if (trace.result.error) {
console.error('Transaction would fail:', trace.result.error);
return false;
}
console.log('Transaction would succeed');
console.log('Gas estimate:', trace.result.gasUsed);
return true;
}
return false;
}
Compare State Changes
async function compareStateChanges(txHash: Keccak256.Keccak256Hash) {
// Get pre-state
const preTrace = await provider.debug_traceTransaction(txHash, {
tracer: 'prestateTracer'
});
if (!preTrace.error) {
const preState = preTrace.result;
// Get transaction receipt for post-state
const receipt = await provider.eth_getTransactionReceipt(txHash);
console.log('Accounts modified:', Object.keys(preState));
}
}
Node Requirements
Debug methods require specific node configuration:
Geth:
geth --http --http.api="eth,debug,net,web3"
Erigon:
erigon --http --http.api="eth,debug,trace,net,web3"
Hardhat:
// Enabled by default in Hardhat Network
Anvil:
anvil --host 0.0.0.0
# Debug methods enabled by default
- Tracing is expensive - Can take several seconds for complex transactions
- Use timeouts - Prevent hanging on long traces
- Disable unused features -
disableMemory, disableStack for faster traces
- Production nodes - Usually disable debug methods for security
Type Reference
All parameter and return types are defined in the JSON-RPC types module.
Next Steps