Storage writes of a transaction
Open this transaction in TraceFast →
Every contract storage slot a transaction wrote, in execution order: which contract's storage, which frame wrote it and whose code ran there, the slot, the value written, and the value the slot held before where that can be established. Contract storage is the persistent key-value store every contract keeps — balances, owners, configuration; see the EVM on ethereum.org.
GET https://tracefast.xyz/api/v1/chains/1/transactions/{hash}/storage-writes
| Parameter | In | Type | Notes |
|---|---|---|---|
hash | path | string | 0x-prefixed, 64 hex characters, any case |
limit | query | integer, optional | writes per page, 1..200, default 50 |
cursor | query | string, optional | nextCursor of the previous page. Valid only for this method and this transaction |
Access — an API key on the Investigation plan or higher (plans), or no key at all: pay per call with x402 at the same path on https://mpp.tracefast.xyz/api/v1, at the price its 402 states. As a tool for AI agents: get_transaction_storage_writes on the MCP server. Stable — see stability.
chains/1 is a literal: the method serves Ethereum mainnet data. Other chain
ids answer 404 chain_not_supported. There are no other parameters — an
unknown one is refused rather than ignored.
What it covers, and what it does not
- The storage owner and the code are two addresses. On a
delegatecalla proxy runs its implementation's code against its own storage:storageAddressis the contract whose storage changed,executionAddressthe contract whose code wrote it. - The value before is stated only when it can be.
valueBeforeis present only withvalueBeforeStatus: resolved.not_computedmeans the prior value has not been computed for this write yet — it is not a statement that the slot was empty. - Writes are computed up to a block.
meta.coverage.storageWritesThroughBlockis the last block writes have reached. For a transaction in a later block the method answers422 block_not_availablewithreason: coverage_gap— the writes are not available yet, which says nothing about what the transaction wrote. An emptywriteslist is never served for such a transaction. - At most 5 000 slots. When a transaction wrote more, the last page says so
with
writesTruncated: true.
Response
200 application/json, here with ?limit=2 — a USDC transfer, which updates
two balances through the proxy's delegatecall:
{
"data": {
"hash": "0xc41b41fb1c3eea59ea87b9e90edf476fb202e8daf02f19f469cdf497adbc76e0",
"blockNumber": 25920000,
"txIndex": 3,
"writes": [
{
"writeIndex": 0,
"writeIndexStatus": "present",
"storageAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"executionAddress": "0x43506849d7c04f9138d1a2050bbf3a0c054402dd",
"callerAddress": "0x978e75381d64fb18af7112e42fa76a211a773456",
"storageKey": "0xb4999ac4e72c403d0684d9ce54cbcb1cf6ff12691c1b573caa0f80fe2a7d4d55",
"newValue": "0x00000000000000000000000000000000000000000000000000000018de35c669",
"valueBefore": "0x0000000000000000000000000000000000000000000000000000001907efdfad",
"valueBeforeStatus": "resolved",
"callPath": "00000000",
"callDepth": 2,
"callType": "delegatecall"
},
{
"writeIndex": 1,
"writeIndexStatus": "present",
"storageAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"executionAddress": "0x43506849d7c04f9138d1a2050bbf3a0c054402dd",
"callerAddress": "0x978e75381d64fb18af7112e42fa76a211a773456",
"storageKey": "0x995f8903a930b1943e02e2dfd5e2735613745e48d63899f95cc3b0a02df45267",
"newValue": "0x0000000000000000000000000000000000000000000000000000000029ba1944",
"valueBefore": "0x0000000000000000000000000000000000000000000000000000000000000000",
"valueBeforeStatus": "resolved",
"callPath": "00000000",
"callDepth": 2,
"callType": "delegatecall"
}
],
"writesTruncated": false
},
"meta": {
"chain": "ethereum",
"timestamp": 1790540650866,
"cached": false,
"asOfBlock": 25920000,
"docs": "https://docs.tracefast.xyz/api/transaction-storage-writes",
"coverage": {
"storageWritesFromBlock": 49018,
"storageWritesThroughBlock": 26071062
}
}
}The storage is the USDC proxy's; the code that wrote it is the implementation,
0x4350…02dd. The sender's slot went down by the amount sent; the
recipient's went from zero to the same amount.
data
| Field | Meaning |
|---|---|
hash | the transaction, lowercase |
blockNumber, txIndex | its block and index within the block |
writes[] | this page, in execution order — the order of writeIndex |
writesTruncated | true on the last page when the transaction wrote more than 5 000 slots: the first 5 000 in execution order are served, the rest are not |
nextCursor | pass it back as cursor for the next page. Absent on the last page |
A write
| Field | Meaning |
|---|---|
storageAddress | the contract whose storage was written |
executionAddress | the contract whose code executed the write — differs from storageAddress on a delegatecall |
callerAddress | the caller of the writing frame |
storageKey | the slot, 32 bytes, 0x-hex |
newValue | the value written, 32 bytes, 0x-hex |
valueBefore | the value the slot held before this write, 32 bytes. Present only when valueBeforeStatus is resolved. All zeroes is a real zero — the slot had never been written, or had been cleared |
valueBeforeStatus | resolved — valueBefore is this write's own; not_derivable — the prior value cannot be established for this write and never will be: the order of writes is not recorded for its block, or a system call rewrites the slot after the transaction; not_computed — the prior value has not been computed for this write yet |
writeIndex | the write's execution ordinal within the transaction, where recorded. Numbers may skip: writes undone by a reverted call are not listed |
writeIndexStatus | present, or not_recorded — the order of writes is not known for this block (blocks below 2 675 000), which is not the same as "write 0" |
callPath | the writing frame's address in the call tree — the same callPath as on the execution trace. Absent when the frame was not recorded |
callDepth | depth of the writing frame; 1 is the top-level call |
callType | call, callcode, delegatecall, staticcall, create, create2 |
meta.coverage
| Key | Meaning |
|---|---|
storageWritesFromBlock | the first block writes are served from; an older transaction is refused with 422. Absent when that height is not known |
storageWritesThroughBlock | the last block writes have reached. A transaction above it is refused with 422 coverage_gap — see Errors |
Pagination
Pages are keyset, not offset. Pass nextCursor back as cursor until it is
absent; keep the same hash. A cursor opens only for this method and this
transaction; any other use, or a cursor altered in transit, answers 400 invalid_cursor — restart from the first page. See
pagination.
Errors
| Status | code | When | details |
|---|---|---|---|
| 400 | bad_request | the hash is not 0x plus 64 hex characters | reason: tx_hash_invalid |
| 400 | bad_request | limit is outside 1..200 | reason: limit_out_of_range, limit, maxLimit: 200 |
| 400 | invalid_cursor | the cursor is not valid for this request | reason: invalid_cursor |
| 404 | not_found | no transaction with this hash is known | — |
| 422 | block_not_available | the transaction is below the height storage writes are served from | reason: block_not_available, minAvailableBlock when that height is known |
| 422 | block_not_available | the hash is unknown while recent blocks are in a coverage gap; ask again later | reason: coverage_gap, coverageGapFromBlock, coverageGapToBlock, maxAvailableBlock |
| 422 | block_not_available | the transaction is above storageWritesThroughBlock: its writes are not available yet. The range is open-ended, so there is no coverageGapToBlock | reason: coverage_gap, maxAvailableBlock, coverageGapFromBlock |
The last refusal, for a transaction in block 25948983:
{
"error": {
"code": "block_not_available",
"details": {
"coverageGapFromBlock": 25925129,
"maxAvailableBlock": 25925128,
"reason": "coverage_gap"
},
"message": "the storage writes of this transaction are not available yet: they are available up to block 25925128. This says nothing about what the transaction wrote — retry later, or ask about a transaction at or below block 25925128.",
"requestId": "01a08cba-809b-73e1-8700-e53656d3f718"
}
}It says nothing about the transaction's outcome or what it wrote; ask again
later, or ask about a transaction at or below maxAvailableBlock.
Malformed input, unknown parameters and the key check's 401/403/429 are the same for every method — see conventions and API keys.
Related pages
- Execution trace of a transaction — the frames these writes belong to
- Call frames of a transaction, paged — every frame with its calldata and logs
- Balance of one token on an address — a balance read straight from token storage
- Storage Analytics — storage-write activity across the network, in the app
Last updated 22 Oct 2026, 08:06 UTC · verified against TraceFast v1.0.261 · Markdown