# debug_traceBlock - Ethereum RPC Method

Traces all transactions in a block on Ethereum 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 Ethereum?** Build on the world's leading smart contract platform with the largest developer ecosystem with battle-tested security, institutional adoption, and unmatched ecosystem with $166B+ TVL.

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 Ethereum - ensure your plan includes debug namespace support.

## When to Use This Method

`debug_traceBlock` is valuable for DeFi developers, NFT creators, and enterprise blockchain teams:

- **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 Ethereum
- **MEV Analysis** - Analyze transaction ordering, sandwich attacks, and arbitrage patterns by tracing full block execution for DeFi protocols (60% market share), NFT marketplaces, DAOs, and enterprise dApps
- **Protocol Research** - Replay historical blocks from RLP data to study state transitions and EVM behavior

## Best Practices

- Requires archive node access; not available on standard full nodes
- Block traces can be very resource-intensive on densely packed blocks
- Consider tracing individual transactions instead for targeted analysis
- Prefer debug\_traceBlockByNumber or debug\_traceBlockByHash for simpler workflows

## Request Parameters

- `blockPayload` (`DATA, required`): Serialized block payload as a hex string
- `tracerConfig` (`Object, optional`): Tracer configuration object (see options below)

## Request Example

```json
{
  "jsonrpc": "2.0",
  "method": "debug_traceBlock",
  "params": [
    "0xf90217a0...SERIALIZED_BLOCK_PAYLOAD",
    {
      "tracer": "callTracer"
    }
  ],
  "id": 1
}
```

## Response Fields

- `result` (`Array<Object>, required`): Array of trace objects, one per transaction
- `result[].result` (`Object, required`): Trace output (structure depends on tracer used)
- `result[].txHash` (`DATA, required`): Transaction hash for this trace
- `gas` (`QUANTITY, required`): Gas provided
- `returnValue` (`DATA, required`): Return value of the call
- `structLogs` (`Array, required`): Array of opcode execution steps
- `structLogs[].pc` (`QUANTITY, required`): Program counter
- `structLogs[].op` (`string, required`): Opcode name
- `structLogs[].gas` (`QUANTITY, required`): Remaining gas
- `structLogs[].gasCost` (`QUANTITY, required`): Gas cost of this opcode
- `structLogs[].depth` (`QUANTITY, required`): Call depth
- `type` (`string, required`): Call type (CALL, DELEGATECALL, STATICCALL, CREATE)
- `from` (`DATA, required`): Sender address
- `to` (`DATA, required`): Recipient address
- `value` (`QUANTITY, required`): Value transferred in wei
- `gas` (`QUANTITY, required`): Gas provided
- `gasUsed` (`QUANTITY, required`): Gas consumed
- `input` (`DATA, required`): Call data
- `output` (`DATA, required`): Return data
- `calls` (`Array, required`): Sub-calls made during execution

## Successful Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "txHash": "0xabc123...",
      "result": {
        "type": "CALL",
        "from": "0x1234567890abcdef1234567890abcdef12345678",
        "to": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
        "value": "0xde0b6b3a7640000",
        "gas": "0x76c0",
        "gasUsed": "0x5208",
        "input": "0x",
        "output": "0x"
      }
    },
    {
      "txHash": "0xdef456...",
      "result": {
        "type": "CALL",
        "from": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
        "to": "0x1234567890abcdef1234567890abcdef12345678",
        "value": "0x0",
        "gas": "0x1e848",
        "gasUsed": "0xb841",
        "input": "0xa9059cbb...",
        "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
        "calls": [
          {
            "type": "DELEGATECALL",
            "from": "0x1234567890abcdef1234567890abcdef12345678",
            "to": "0xfedcba0987654321fedcba0987654321fedcba09",
            "gas": "0x1a5b4",
            "gasUsed": "0x9c40",
            "input": "0xa9059cbb...",
            "output": "0x0000000000000000000000000000000000000000000000000000000000000001"
          }
        ]
      }
    }
  ]
}
```

## Error Responses

### Error Response

- Code: `-32000`

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32000,
        "message": "invalid block payload"
  }
}
```

## Code Examples

cURL
JavaScript
Python
Go

```bash
curl -X POST https://api-ethereum-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
  }'
```

```javascript
import { JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider('https://api-ethereum-mainnet.n.dwellir.com/YOUR_API_KEY');

// First, obtain the serialized block payload from your tracing workflow
// Then trace all transactions in the block
const blockRlp = '0xf90217a0...'; // Serialized block payload

// Trace with call tracer
const traces = await provider.send('debug_traceBlock', [
  blockRlp,
  { tracer: 'callTracer' }
]);

for (const trace of traces) {
  console.log(`Tx: ${trace.txHash}`);
  console.log(`  Type: ${trace.result.type}`);
  console.log(`  From: ${trace.result.from}`);
  console.log(`  To: ${trace.result.to}`);
  console.log(`  Gas used: ${parseInt(trace.result.gasUsed, 16)}`);
}

// Trace with default opcode tracer (verbose output)
const opcodeTraces = await provider.send('debug_traceBlock', [
  blockRlp,
  { disableStorage: true, disableStack: false }
]);

for (const trace of opcodeTraces) {
  console.log(`Tx: ${trace.txHash}, Opcodes: ${trace.result.structLogs.length}`);
}
```

```python
import requests
import json

def trace_block_by_rlp(rlp_data, tracer='callTracer'):
    response = requests.post(
        'https://api-ethereum-mainnet.n.dwellir.com/YOUR_API_KEY',
        json={
            'jsonrpc': '2.0',
            'method': 'debug_traceBlock',
            'params': [rlp_data, {'tracer': tracer}],
            'id': 1
        }
    )
    return response.json()['result']

# Trace all transactions in a block
block_rlp = '0xf90217a0...'  # Serialized block payload
traces = trace_block_by_rlp(block_rlp)

for trace in traces:
    tx_hash = trace.get('txHash', 'unknown')
    result = trace['result']
    gas_used = int(result['gasUsed'], 16)
    print(f'Tx {tx_hash}: {result["type"]} | Gas: {gas_used}')

    # Print sub-calls
    for call in result.get('calls', []):
        print(f'  -> {call["type"]} to {call["to"]}')

# Using web3.py
from web3 import Web3

w3 = Web3(Web3.HTTPProvider('https://api-ethereum-mainnet.n.dwellir.com/YOUR_API_KEY'))

traces = w3.provider.make_request('debug_traceBlock', [
    block_rlp,
    {'tracer': 'callTracer'}
])
print(f'Traced {len(traces["result"])} transactions')
```

```go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "log"
    "net/http"
)

type TraceResult struct {
    TxHash string      `json:"txHash"`
    Result CallTrace   `json:"result"`
}

type CallTrace struct {
    Type    string      `json:"type"`
    From    string      `json:"from"`
    To      string      `json:"to"`
    Value   string      `json:"value"`
    Gas     string      `json:"gas"`
    GasUsed string      `json:"gasUsed"`
    Input   string      `json:"input"`
    Output  string      `json:"output"`
    Calls   []CallTrace `json:"calls"`
}

func main() {
    blockRlp := "0xf90217a0..." // Serialized block payload

    payload := map[string]interface{}{
        "jsonrpc": "2.0",
        "method":  "debug_traceBlock",
        "params":  []interface{}{blockRlp, map[string]string{"tracer": "callTracer"}},
        "id":      1,
    }

    body, _ := json.Marshal(payload)
    resp, err := http.Post("https://api-ethereum-mainnet.n.dwellir.com/YOUR_API_KEY", "application/json", bytes.NewReader(body))
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    data, _ := io.ReadAll(resp.Body)

    var response struct {
        Result []TraceResult `json:"result"`
    }
    json.Unmarshal(data, &response)

    for _, trace := range response.Result {
        fmt.Printf("Tx: %s | Type: %s | Gas: %s\n",
            trace.TxHash, trace.Result.Type, trace.Result.GasUsed)
    }
}
```

## Common Use Cases

### 1. Block-Level Gas Profiling

Analyze gas consumption across all transactions in a block on Ethereum:

```javascript
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 Ethereum blocks:

```javascript
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:

```python
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-ethereum-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)')
```

## Related Methods

- [`debug_traceBlockByHash`](https://www.dwellir.com/docs/ethereum/debug_traceBlockByHash) - Trace all transactions in a block by hash (more commonly used)
- [`debug_traceBlockByNumber`](https://www.dwellir.com/docs/ethereum/debug_traceBlockByNumber) - Trace all transactions in a block by number
- [`debug_traceTransaction`](https://www.dwellir.com/docs/ethereum/debug_traceTransaction) - Trace a single transaction by hash
- [`debug_traceCall`](https://www.dwellir.com/docs/ethereum/debug_traceCall) - Trace a call without creating a transaction
