FORENSIAWeb3 forensicsOpen workspace

Following transfers Forensia has already captured

Follow captured transfers links same-asset movements inside one existing result, with no new requests. It shows up to 16 records and two hops, and it names gaps as gaps.

· Forensia · 6 min read · Tracing, Evidence

When you look up a wallet or a transaction, the result already contains a list of transfers. Some of them may connect: one address receives an asset, and later the same address sends that asset on. Spotting those connections by eye in a long activity list is slow, and it is easy to connect things that should not be connected.

Forensia has a view called Follow captured transfers that does this joining for you, using only the records already in the result. It makes no network requests and it does not change the capture. It is the foundation for tracing on EVM networks such as Ethereum, not a complete tracer, and it does not fetch more history on its own.

What it gives you is an ordered sequence of possible connections, and an explicit stop message wherever the captured records run out.

#Plain languageJoining the dots you already have, and nothing else

Imagine a box of bank slips from one afternoon. You can lay them out so that a slip paying Alex is followed by a later slip where Alex pays someone else in the same currency. That layout is useful. It is also limited: it only covers the slips in the box, and it cannot tell you that the second payment was made with the money from the first.

The view works the same way. It starts from one transfer, finds the recipient, and looks for later transfers of the exact same asset sent by that recipient within the same result. If there are none, it tells you whether that is because the recipient never appears as a sender in the records, or because the only candidates were a different asset or could not be ordered.

The wording in the workspace is deliberate: these are possible connections, not proof that the same funds moved or that the addresses share an owner.

#How it worksUsing Follow captured transfers on Overview

  1. Run a lookup on an EVM address or transaction and stay on Overview.
  2. Open the section called Follow captured transfers.
  3. Pick a row under Starting transfer. Each option shows the two shortened addresses, the block number, and whether it is Token or Native.
  4. Press Show next captured transfer to reveal one record at a time. A line above the list tells you how many of the selected records are shown.
  5. Read the sentence under each record. It says how many later same-asset records were found, or why the trail stops there.
  6. Open Asset identity and supporting records for the exact asset key, the raw amount, the transaction hash, and buttons to Read activity record or Inspect source.
  7. If you jump to a source or activity record, use Back to captured trail to return with your starting choice and position intact.

Each later record carries a line such as: recipient of record 1 is the sender here, hop 1. It also carries an execution label taken from the captured evidence, for example receipt-confirmed, provider-reported, or unverified.

#Technical detailHow a captured row becomes an edge

The logic is in capturedTransferSet and capturedTransferTrail. The first function decides which rows are usable at all. The second walks them.

Network and input gate

The result must be an EVM capture whose chain key, chain ID and network ID agree, with the network ID in the form eip155 followed by the chain ID. The capture must record a valid latest block, which becomes the boundary. Input rows are the activity list plus any structured rows from the existing bounded native continuation finding. If the combined input exceeds 512 rows, the view builds nothing. It does not take a prefix, because a contradictory duplicate outside the prefix would escape checking.

Occurrence identity

A row is identified as an occurrence, never by amount, address or symbol.

KindOccurrence keyNotes
Top-level native valuenative:{transaction hash}Rows whose ID marks them as internal calls are not eligible
ERC-20 Transfer eventtoken:{transaction hash}:{log index}Log index may be decimal or hex and is normalized. A missing position abstains
Anything elsenoneCounted as excluded

Asset identity is equally strict. Native value is keyed as eip155:{chain id}/native with 18 decimals. A token is keyed as eip155:{chain id}/erc20:{contract address}. Symbols and display amounts never create an edge.

Rows that are dropped

Rows sharing an occurrence key are grouped and must agree with each other on asset, raw value, sender, recipient, block number and timestamp. There is no majority vote. The whole group is excluded if any row has a failed status, a non-positive raw amount, a conflicting-source flag, a decimal-scale conflict, a malformed or zero address on either side, the same sender and recipient, or a block number missing or beyond the capture boundary. Zero-address rows are how mints and burns are kept out.

A surviving occurrence also needs at least one supporting source record that is marked captured, has a unique ID, and, where the source is an eth_getTransactionReceipt, eth_getTransactionByHash or debug_traceTransaction request, was actually made for that transaction hash. If one token shows two different decimal scales across occurrences, every occurrence of that token is excluded. Execution status is success only if every row in the group says so. Otherwise it stays unknown.

The walk

Starting choices are occurrences in the looked-up transaction, or occurrences sent by the looked-up address. From a step, the next candidates are occurrences whose sender equals the current recipient. A candidate is eligible only if it has the same asset key, sits in a strictly later block, is a different transaction, and has a strictly later timestamp where both timestamps exist.

Traversal is breadth-first. Within a frontier, records are ordered by block number and then by occurrence key. That is a navigation order, not a global timeline and not a ranking. An address may be revisited, but each occurrence appears once, and when a record is reachable from two branches the view says it already appears elsewhere instead of counting it twice.

Limit in EVM_CAPTURED_TRAIL_LIMITSValue
records (input rows before the view abstains)512
roots (starting choices offered)32
steps (records displayed in one trail)16
depth (hops beyond the start)2

Stop messages

ConditionWhat the view says
Step is at hop 2Two-hop limit reached. Later activity was not followed
Recipient never appears as a senderA history gap, not proof that the trail ended
Recipient sends, but nothing eligibleNo later-block transfer of this exact asset. Other assets or uncertain order are not connected
Eligible records already shownNot counted twice
16-record cap reachedAdditional eligible records remain unchecked here

The counts of excluded input rows, omitted starting choices and omitted records are disclosed in the view.

#LimitsWhat the captured trail cannot show

  • It does not show that the same funds moved. A recipient sending the same asset later is an account sequence. No amounts are allocated, equated or summed.
  • It does not show common ownership, a beneficiary, or intent.
  • It only sees the capture. A missing branch means missing eligible captured data, not an inactive address.
  • Two transfers in the same block are never ordered, even when their log positions differ.
  • Internal calls, NFTs, mints, burns, self-transfers, zero-value rows, failed transactions and cross-network hops are not followed.
  • A token event is evidence that the contract emitted a log. It is not an independent check of a balance change, and a token name is whatever the source reported.
  • The checks compare normalized records with each other. They do not authenticate the provider or replay raw responses.
  • Service and bridge boundaries are not classified by this view. The separate ERC-20 recipient check is where known shared services stop a path.
  • Save result keeps the underlying capture. It does not keep your starting choice or how far you revealed the trail.

The engineering notes include a real example of exactly that. A wallet lookup captured one 1.074634 ETH transfer at block 25,994,464 with receipt-confirmed execution, and no outflow from the recipient was in the captured set. The view reported a history gap and stopped. No multi-hop result was claimed from it.