FORENSIAWeb3 forensicsOpen workspace

What a transaction changed

How the before-and-after state of the accounts a transaction touched is captured, and how tightly it is pinned down.

2 min read · Transaction analysis

#Plain languageIn plain terms

Events are what contracts say happened. State is what actually changed: balances, counters, stored values, code. For the strongest reading of a transaction you want both.

On Ethereum, Forensia can ask a node for the exact before and after of every account the transaction touched. It treats that answer carefully, pinning it between two checks of the block so it cannot be mixed up with a different version of the chain.

#How it worksHow it works

  1. Confirm the network.
  2. Read the block and confirm the transaction sits where expected.
  3. Read the receipt and confirm it matches.
  4. Ask for the state difference caused by the transaction.
  5. Read the block again and confirm nothing moved while this was happening.

All five reads go to the same server. If the first read falls back to another source, every later read is pinned to that one.

#Technical detailThe exact rules

The state request is debug_traceTransaction with the prestateTracer in diff mode, with code and storage both enabled. It is made only when the receipt reports a clear success or failure, and the receipt read in step three must report that same status and position.

LimitValue
Accounts64
Storage slots256
Code bytes262,144
Response size1 MiB
Total time15 seconds
Requests6

The diff is parsed strictly. It must have exactly a pre and a post section, account keys must be valid addresses, and the only fields allowed are balance, nonce, code and storage. If any limit is exceeded, nothing is kept. A partial diff would be misleading, because in this format a missing field means "unchanged".

The sixth request is optional. When the diff does not carry the starting code of a called contract, one more prestateTracer read asks for code at the start of the transaction, for at most 4 call targets, inside the same two block checks. If it is skipped or fails, the diff is still kept and the code stays unknown.

Change shownRendered as
BalanceETH, to 18 decimals
NonceThe account's sequence counter before and after
CodeSize in bytes and Keccak-256 hash
StorageThe raw 32-byte slot and its before and after values

Each account is marked modified, created or deleted. The capture has a status: captured, unavailable, unsupported, invalid, limit or conflict. In the interface this is "Before and after this transaction", inside "Inspect transaction steps" on the Overview view.

#LimitsWhat it does not tell you

  • Ethereum mainnet only. Other networks report unsupported.
  • Balance changes include fees.
  • A failed transaction can still show changes, such as the fee. They do not establish successful calls or transfers.
  • Storage slots are raw. No variable names are inferred.
  • Values written and then overwritten or reverted within the transaction do not appear.
  • The diff does not say which internal call caused a write.
  • Many public sources do not offer this tracer.