Following ETH onward
How Forensia finds what a recipient did next with native currency, one bounded step at a time.
#Plain languageIn plain terms
Someone receives ETH. The obvious next question is: what did they do after that? Answering it for every recipient, forever, is not possible on public sources. Answering it for one recipient, over a fixed stretch of blocks, is.
Forensia takes one confirmed transfer and looks for the recipient's next outgoing transaction. If it finds one, you can repeat the step from there. It follows activity, not coins. It never claims the same money moved on.
#How it worksHow it works
Every wallet has a counter that goes up by one each time it sends a transaction. If the counter is higher at a later block than it was when the wallet received the money, the wallet sent something in between. The lookup uses that to find the block without reading every block on the way.
- Re-confirm the starting transfer and its receipt from the source.
- Fix the end of the search window.
- Read the recipient's counter at the start and at the end of the window.
- If it went up, halve the window repeatedly to find the first block where it changed.
- Read that one block and list the recipient's outgoing transfers in it.
- Check each against its receipt. Only successful ones are kept.
#Technical detailThe exact rules
| Limit | Value |
|---|---|
| Search window | 15,000 blocks after the starting transfer, and never past the latest block of the original lookup |
| Requests | 32 |
| Outgoing transfers receipt-checked | 4 |
| Total time | 22 seconds |
| Checks per open result, shared by all starting transfers, failures included | 4 |
| Hops beyond the start | 2 |
The counter is read with eth_getTransactionCount at specific historical block numbers. The window's upper edge is a fixed block number, never the moving latest tag, so a second run reads the same range. The edge is set once and later hops cannot slide it forward.
Each check first asks the source for its network ID with eth_chainId and stops if it is not the expected network. Every later request in that check goes to the same endpoint. Another configured source can only stand in for that first request.
Inside the located block, a candidate must be sent by the recipient, carry a value above zero, and go to a different, non-zero address. Candidates are ordered by their position in the block. After the search, the pinned blocks are read again. If any hash changed during the work, the whole step is rejected.
| Result | Meaning |
|---|---|
records-returned | At least one successful outgoing transfer was found. |
no-nonce-increase | The counter did not change in the window. |
no-eligible-transfer | The counter changed, but not through a positive native transfer. |
| A branch stops when | Recorded as |
|---|---|
| The recipient already appeared on this path | cycle |
| The transfer sits at the window's edge | boundary-limit |
| Two hops have been followed | depth-limit |
| Four checks have been used | check-limit |
The result lists every recipient with a sentence giving its stop reason, under "Recipients and stop reasons".
#LimitsWhat it does not tell you
- Only the first block where the counter changed is read. Later activity in the window is not.
- The counter also rises for failed calls, contract interactions and delegations, so a change is a search hint, not a payment.
- No change in the counter is not inactivity. Incoming transfers, token movements and internal transfers do not touch it.
- The starting transfer's own block is never searched, so a same-block onward transfer is missed.
- Transfers in the same block are listed in a stable order for navigation. That is not a claim about execution order.