Skip to main content
Track internal transactions (traces) to analyze complex contract interactions and value flows through multiple contracts.

Use Case

Call traces help you:
  • Analyze DEX trades with multiple hops
  • Track value flows through proxy contracts
  • Monitor internal contract calls
  • Debug complex contract interactions

Code Example

curl --compress -X POST "https://portal.sqd.dev/datasets/ethereum-mainnet/stream" \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "evm",
    "fromBlock": 18000000,
    "toBlock": 18010000,
    "fields": {
      "block": {
        "number": true
      },
      "trace": {
        "type": true,
        "callFrom": true,
        "callTo": true,
        "callValue": true,
        "callInput": true,
        "callResultOutput": true,
        "callResultGasUsed": true,
        "error": true
      }
    },
    "traces": [{
      "type": ["call"]
    }]
  }'
Try it yourself with the interactive query interface below:

Key Parameters

ParameterDescription
typeTrace type: call (contract calls) or create (contract deployments)
callFromCaller address
callToCallee address
callValueETH value transferred in the call
callInputCall input data
callResultOutputCall output data
callResultGasUsedGas used by the call
errorError message if trace failed
Portal supports two trace types: call for regular contract calls and create for contract deployments. Other EVM trace types like staticcall, delegatecall, and callcode are normalized to call type.

Expected Output

The raw HTTP response nests the requested call*/create* fields under action and result sub-objects rather than returning them flat, and numeric values like action.value are hex wei:
{
  "header": {
    "number": 18000123
  },
  "traces": [
    {
      "type": "call",
      "error": null,
      "action": {
        "from": "0x1234...",
        "to": "0x5678...",
        "value": "0xde0b6b3a7640000",
        "input": "0xa9059cbb..."
      },
      "result": {
        "gasUsed": "0xb043",
        "output": "0x0000000000000000000000000000000000000000000000000000000000000001"
      }
    }
  ]
}
transactionHash is not a trace field. To attach a trace to its transaction hash, set "transaction": true in the traces filter and request fields.transaction.hash; the hash arrives on the joined transactions row and you match it by transactionIndex:
"traces": [{ "type": ["call"], "transaction": true }],
"fields": {
  "trace": { "type": true, "transactionIndex": true, "callFrom": true, "callTo": true, "callValue": true },
  "transaction": { "transactionIndex": true, "hash": true }
}
Trace fields are opt-in, so request transactionIndex on both the trace and the transaction selectors. That shared index is the key you match on, since the joined transaction arrives in a separate transactions array.The @subsquid/portal-client typed client flattens the action/result nesting back to the requested selector names (trace.callFrom, trace.callResultGasUsed), as the TypeScript snippet above shows. The nesting only applies to the raw HTTP response.

Filter by Specific Contract

Track all calls to or from a specific contract:
curl --compress -X POST "https://portal.sqd.dev/datasets/ethereum-mainnet/stream" \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "evm",
    "fromBlock": 18000000,
    "toBlock": 18010000,
    "fields": {
      "trace": {
        "type": true,
        "callFrom": true,
        "callTo": true,
        "callValue": true
      }
    },
    "traces": [{
      "callTo": ["0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"]
    }]
  }'
Traces include both successful and failed calls. Check the error field to filter failed traces.

Analyze Value Flows

Track ETH transfers through internal calls:
const blocks = await dataSource.getBlocks({
  from: 18000000,
  to: 18010000,
  fields: {
    trace: { type: true, callFrom: true, callTo: true, callValue: true },
  },
  traces: [
    {
      type: ["call"],
    },
  ],
});

// Filter traces with value transfers
for (const block of blocks) {
  for (const trace of block.traces) {
    if (BigInt(trace.callValue) > 0n) {
      console.log(`${trace.callFrom}${trace.callTo}: ${trace.callValue} wei`);
    }
  }
}

Performance Tips

  1. Filter by type: Specify trace types to reduce data volume
  2. Use callTo/callFrom: Filter by specific contracts
  3. Request minimal fields: Omit input and output if not needed
  4. Post-filter errors: Filter failed traces in your code if needed
Traces can be very numerous. Use specific filters to avoid processing millions of traces.

Query Transactions

Monitor transaction activity

Index DEX Swaps

Track DEX trading with traces

Query Event Logs

Track smart contract events

API Reference

View complete API docs