Skip to main content
GoldRush exposes EVM transaction traces, which are the internal value transfers that occur during smart contract execution, through the Foundational API.

What are internal transactions?

An EVM transaction is “external” when it originates from an externally-owned account (EOA) and is broadcast to the network. Once it begins executing, the contract it calls can in turn invoke other contracts and move native value between accounts. These nested value transfers are called internal transactions (or internal transfers, or traces). Internal transactions are not stored as separate transactions on-chain. They only exist as side effects of the parent transaction’s execution and can only be reconstructed by re-executing the transaction against an archive node. They are essential for accurately tracking:
  • Native token movement triggered by contracts (e.g. a router contract forwarding ETH to a recipient).
  • DEX, lending, and bridge flows where the EOA-visible to_address is a contract, not the ultimate recipient of funds.
  • Wallet balance reconciliation, accounting, and tax reporting - without internal transactions, native-token balance deltas often cannot be explained from external transactions alone.
  • Failed sub-calls within a multi-step transaction that still consumed gas.

Enabling traces

Traces are opt-in via a query param on the Transactions API. Internal transfers cost 0.05 credits per item where supported:
  • with-internal - includes internal transfers/transactions in the response.
When enabled, each transaction item in the response includes an internal_transfers array describing the from_address, to_address, value (in wei), and gas_limit of each internal transfer.

API endpoints with trace support

with-internal vs. raw trace_* / debug_* (JSON-RPC)

A common point of confusion is how the Foundational API’s with-internal param relates to the raw trace_* and debug_* JSON-RPC methods. They solve different problems. with-internal is built for wallet-level internal transaction history: ask for one address and get back its internal transfers, already decoded and attached to each transaction, across the supported chains. The raw trace_* / debug_* methods are low-level per-transaction or per-block primitives - powerful, but they do not answer “show me this wallet’s internal transfers” without significant client-side work.

Why raw RPC is impractical for wallet history

Reconstructing a single wallet’s internal-transfer history from raw traces is expensive and chain-dependent:
  • trace_filter (Ethereum / Erigon-style nodes) returns matching internal calls directly, but a wallet can be either the sender or the recipient, so you must scan the block range twice - once with fromAddress and once with toAddress. Even chunking at 1M blocks per request, a full-history scan is roughly 50 calls per direction (~100 total) on Ethereum alone.
  • trace_filter is unsupported on OP-stack L2s (and many other chains) unless you run the node yourself or your RPC vendor has explicitly enabled it. The fallback is debug_traceBlockByNumber, which forces you to fetch and trace every block in the range and then filter client-side for calls whose from or to matches the wallet - far more calls and far more data to walk.
  • In both cases you still have to walk the resulting call tree yourself and decode raw payloads to make the data usable.

The honest trade-off

For a single transaction on eth-mainnet, calling trace_transaction (or debug_traceTransaction) directly over raw RPC is cheaper than the Foundational API. What with-internal adds is:
  • A decoded payload rather than raw call frames.
  • No client-side call-tree walking - internal transfers arrive flattened and attached to each transaction.
  • Uniform behavior across chains, including chains where trace_filter is unavailable.
This is the same trade-off as fetching the balance of a single token: you can compose it from raw eth_calls, but for anything beyond one-off lookups the enriched, multi-chain endpoint is what saves you the integration work.

When to use which

You want…Use
A wallet’s full internal-transfer history, decodedFoundational API with-internal
Internal transfers attached to a known transaction, decodedFoundational API with-internal on Get a transaction
Opcode-level / Parity-style trace of one known tx on Ethereumtrace_transaction / debug_traceTransaction
Custom tracer output (callTracer, prestateTracer, state diff)debug_* / trace_* JSON-RPC

Supported chains

Tracing is currently available on the following chains: