trace_replayBlockTransactions
https://api.triport.io/v1/polygonReplays every transaction in a Polygon block and returns, per transaction, the full Parity-style execution trace plus the state changes it produced.
trace_replayBlockTransactions re-executes all transactions in a single
block against the historical state at that block and returns one result entry
per transaction. Each entry can carry up to three views of what happened: the
Parity-style call trace (the tree of execution frames flattened into an array),
the stateDiff (every storage slot, balance, nonce, and code change the
transaction made), and the low-level vmTrace. Which views you get back is
controlled entirely by the second parameter — you ask for exactly the modes you
need.
This is the heaviest method in the entire Polygon surface. A full state diff
plus call trace for every transaction in a busy Polygon block (typically
50–150 transactions) can run to tens of megabytes of JSON. Request it only when
you genuinely need block-wide replay — for MEV / arbitrage indexing, full DeFi
internal-transfer reconstruction, or forensic audits where you must see both the
execution path and the resulting state for the whole block at once. If you only
need the call tree (and not state diffs), prefer the lighter
trace_block; for a single transaction use
trace_transaction.
It belongs to the premium Parity polygon_trace category and requires Pro
tier. It is rate limited per tier (3 rps on Pro, 10 rps on Business) with a
short burst allowance — there is no daily quota. Because each response is so
large, the practical bottleneck is bandwidth rather than RPS: keep concurrency
to ≤4 in-flight requests to avoid bandwidth contention and request
queueing, and expect multi-second latency per call.
Parameters
Positional params array, [blockParameter, traceTypes]:
blockParameterstringrequired0x-prefixed hex block number (e.g. "0x4470eb3") or a tag ("latest", "earliest").traceTypesarray of stringrequired"trace" (call-frame tree), "stateDiff" (state changes), and "vmTrace" (opcode-level VM trace).Response
result is an array with one entry per transaction in the block, in execution
order. Each entry carries the views you asked for; modes you did not request are
null.
resultarrayresult[].transactionHashstringresult[].outputstringresult[].tracearray | null"trace" was requested). Each frame has action, result, subtraces, traceAddress, and type.result[].trace[].actionobjectcallType/from/to/value/gas/input, or creation fields).result[].trace[].resultobjectgasUsed and output (or an error string if it reverted).result[].trace[].traceAddressarray[] is the top-level call).result[].trace[].subtracesnumberresult[].stateDiffobject | null"stateDiff" was requested), keyed by address. Each account reports balance, nonce, code, and storage; "=" means unchanged, and a { "*": { "from", "to" } } object records a change.result[].vmTraceobject | null"vmTrace" was requested; null otherwise).Errors
| Code | Meaning | When it happens |
|---|---|---|
-32002 | tier_insufficient | Your key is below Pro tier (or lacks the polygon_trace scope). The error data includes current_tier, required_tier, and an upgrade_url. |
-32003 | rate_limited | You exceeded your tier's RPS for polygon_trace (Pro 3 / Business 10), including burst. The data carries limit_rps, burst_capacity, and retry_after_sec — back off and retry. |
-32005 | unauthorized | Missing or invalid Authorization header. |
-32601 | method_unknown | Method not enabled for this key/chain. |
-32602 | invalid params | Bad block parameter, or a traceTypes value other than "trace" / "vmTrace" / "stateDiff". |
All errors use the shared JSON-RPC envelope — see errors.md
for the full structure and the data fields above.
Examples
JavaScript (fetch)
const res = await fetch("https://api.triport.io/v1/polygon", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRIPORT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "trace_replayBlockTransactions",
params: ["0x4470eb3", ["trace", "stateDiff"]],
}),
});
const { result } = await res.json();
console.log(result.length, "transactions replayed");TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const tp = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });
const replays = await tp.polygon.rpc("trace_replayBlockTransactions", [
"0x4470eb3",
["trace", "stateDiff"],
]);
for (const tx of replays) {
console.log(tx.transactionHash, tx.trace?.length ?? 0, "frames");
}Python (triport-sdk)
import os
from triport import Triport
tp = Triport(api_key=os.environ["TRIPORT_API_KEY"])
replays = tp.polygon.rpc(
"trace_replayBlockTransactions",
["0x4470eb3", ["trace", "stateDiff"]],
)
for tx in replays:
print(tx["transactionHash"], len(tx.get("trace") or []), "frames")Notes
- This is the heaviest call on the Polygon surface. A full
trace+stateDiffreplay of a busy block can be tens of megabytes. Throughput is bandwidth-bound, not RPS-bound: hold concurrency to ≤4 in-flight requests, expect multi-second latency, and stream/parse the response incrementally rather than buffering it whole where you can. - Ask only for the modes you use. Dropping
vmTrace(andstateDiffif you don't need it) shrinks the payload dramatically.["trace"]alone is roughly equivalent in content totrace_block, which is cheaper when you don't need state diffs. - Bor frame shapes. Polygon runs the Bor execution layer, so certain frame
types and
callTypeboundaries (e.g.callvsdelegatecall) can render slightly differently from vanilla Geth/Parity. A decoder that handles both shapes will reconcile traces cleanly. - Related methods. For a single transaction use
trace_transaction; for a block-wide call tree without state diffs usetrace_block; to filter traces across a block range usetrace_filter. The Geth-style counterparts aredebug_traceCallanddebug_traceBlockByNumber— all share the same Pro-tierpolygon_tracelimits.