debug_traceBlock - Zetachain RPC Method
Trace all transactions in a block on Zetachain using a serialized block payload. Essential for block-level debugging, gas profiling, and MEV analysis.
Traces all transactions in a block on Zetachain by accepting a serialized block payload. Returns detailed execution traces for every transaction in the block, including opcode-level steps, gas consumption, and internal calls.
Why Zetachain? Build on the universal omnichain blockchain enabling cross-chain smart contracts across 50+ chains including Bitcoin with native Bitcoin support, 50+ chain interoperability via UNISON, no bridging required, and partnerships with Curve and SushiSwap.
Archive Node Required
This method requires an archive node with debug APIs enabled. Standard full nodes prune the historical state needed for transaction tracing. Dwellir provides archive node access for Zetachain — ensure your plan includes debug namespace support.
When to Use This Method
debug_traceBlock is valuable for cross-chain dApp developers, Bitcoin DeFi builders, and teams requiring native multi-chain interoperability:
- Block-Level Debugging — Trace every transaction in a block simultaneously when you have the serialized block payload, useful for offline analysis or replaying captured block data
- Gas Profiling Across Transactions — Measure gas consumption per opcode across all transactions in a block to identify expensive patterns on Zetachain
- MEV Analysis — Analyze transaction ordering, sandwich attacks, and arbitrage patterns by tracing full block execution for omnichain DeFi, native Bitcoin smart contracts, cross-chain asset management, and unified liquidity aggregation
- Protocol Research — Replay historical blocks from RLP data to study state transitions and EVM behavior
Request Parameters
Serialized block payload as a hex string
Tracer configuration object (see options below)
Response Body
Array of trace objects, one per transaction
Trace output (structure depends on tracer used)
Transaction hash for this trace
Gas provided
Return value of the call
Array of opcode execution steps
Program counter
Opcode name
Remaining gas
Gas cost of this opcode
Call depth
Call type (CALL, DELEGATECALL, STATICCALL, CREATE)
Sender address
Recipient address
Value transferred in wei
Gas provided
Gas consumed
Call data
Return data
Sub-calls made during execution
Error Responses
Code Examples
curl -X POST https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "debug_traceBlock",
"params": [
"0xf90217a0...SERIALIZED_BLOCK_PAYLOAD",
{"tracer": "callTracer"}
],
"id": 1
}'Common Use Cases
1. Block-Level Gas Profiling
Analyze gas consumption across all transactions in a block on Zetachain:
async function profileBlockGas(provider, blockRlp) {
const traces = await provider.send('debug_traceBlock', [
blockRlp,
{ tracer: 'callTracer' }
]);
let totalGas = 0;
const txGas = [];
for (const trace of traces) {
const gasUsed = parseInt(trace.result.gasUsed, 16);
totalGas += gasUsed;
txGas.push({
txHash: trace.txHash,
gasUsed,
type: trace.result.type,
hasSubCalls: (trace.result.calls || []).length > 0
});
}
// Sort by gas usage
txGas.sort((a, b) => b.gasUsed - a.gasUsed);
console.log(`Block total gas: ${totalGas}`);
console.log('Top gas consumers:');
for (const tx of txGas.slice(0, 5)) {
const pct = ((tx.gasUsed / totalGas) * 100).toFixed(1);
console.log(` ${tx.txHash}: ${tx.gasUsed} gas (${pct}%)`);
}
return { totalGas, txGas };
}2. MEV Detection and Analysis
Detect sandwich attacks and arbitrage in Zetachain blocks:
async function detectMEVPatterns(provider, blockRlp) {
const traces = await provider.send('debug_traceBlock', [
blockRlp,
{ tracer: 'callTracer' }
]);
const dexInteractions = [];
for (let i = 0; i < traces.length; i++) {
const trace = traces[i];
const calls = flattenCalls(trace.result);
for (const call of calls) {
// Detect swap-like function selectors (e.g., Uniswap swapExactTokensForTokens)
if (call.input && call.input.startsWith('0x38ed1739')) {
dexInteractions.push({
index: i,
txHash: trace.txHash,
to: call.to,
type: 'swap'
});
}
}
}
// Check for sandwich patterns (swap-X-swap by same sender)
for (let i = 0; i < dexInteractions.length - 2; i++) {
const first = dexInteractions[i];
const last = dexInteractions[i + 2];
if (first.txHash !== last.txHash &&
traces[first.index].result.from === traces[last.index].result.from) {
console.log(`Potential sandwich: tx ${first.index} and ${last.index}`);
}
}
return dexInteractions;
}
function flattenCalls(trace) {
const calls = [trace];
for (const sub of trace.calls || []) {
calls.push(...flattenCalls(sub));
}
return calls;
}3. Comparing Block Execution Across Clients
Verify consistent execution by tracing the same block RLP on different clients:
import requests
def trace_on_endpoint(endpoint, block_rlp):
response = requests.post(endpoint, json={
'jsonrpc': '2.0',
'method': 'debug_traceBlock',
'params': [block_rlp, {'tracer': 'callTracer'}],
'id': 1
})
return response.json()['result']
# Compare traces from two different endpoints
block_rlp = '0xf90217a0...'
traces_a = trace_on_endpoint('https://api-zetachain-mainnet.n.dwellir.com/YOUR_API_KEY', block_rlp)
traces_b = trace_on_endpoint('https://other-endpoint.example.com', block_rlp)
# Verify same number of traces
assert len(traces_a) == len(traces_b), 'Transaction count mismatch'
# Compare gas usage per transaction
for i, (a, b) in enumerate(zip(traces_a, traces_b)):
gas_a = int(a['result']['gasUsed'], 16)
gas_b = int(b['result']['gasUsed'], 16)
if gas_a != gas_b:
print(f'Gas mismatch at tx {i}: {gas_a} vs {gas_b}')
else:
print(f'Tx {i}: {gas_a} gas (consistent)')Error Handling
Common errors and solutions:
| Error Code | Description | Solution |
|---|---|---|
| -32000 | Invalid RLP data | Verify the block RLP encoding is correct and complete |
| -32000 | Missing trie node | Node is not an archive node or state has been pruned — use an archive endpoint |
| -32601 | Method not found | Debug namespace is not enabled on the node |
| -32603 | Internal error | Block may be too large to trace — try increasing timeout or use disableStorage |
| -32005 | Rate limit exceeded | Reduce request frequency or upgrade your plan |
| -32002 | Resource not found | The block data could not be resolved — check the RLP encoding |
async function safeTraceBlock(provider, blockRlp, options = {}) {
const defaultOptions = {
tracer: 'callTracer',
timeout: '60s',
...options
};
try {
return await provider.send('debug_traceBlock', [blockRlp, defaultOptions]);
} catch (error) {
if (error.code === -32601) {
throw new Error('debug_traceBlock not available — ensure archive node with debug API');
}
if (error.message?.includes('timeout')) {
console.warn('Trace timed out — retrying with reduced detail');
return await provider.send('debug_traceBlock', [
blockRlp,
{ ...defaultOptions, disableStorage: true, disableStack: true }
]);
}
throw error;
}
}Related Methods
debug_traceBlockByHash— Trace all transactions in a block by hash (more commonly used)debug_traceBlockByNumber— Trace all transactions in a block by numberdebug_traceTransaction— Trace a single transaction by hashdebug_traceCall— Trace a call without creating a transaction
eth_newPendingTransactionFilter
Create a filter for pending transaction notifications on Zetachain. Essential for mempool monitoring, transaction tracking, and MEV opportunity detection for omnichain DeFi, native Bitcoin smart contracts, cross-chain asset management, and unified liquidity aggregation.
debug_traceBlockByHash
Trace all transactions in a block by hash on Zetachain. Investigate specific blocks, analyze execution order, and debug reverts with detailed traces.