Round Trips and Self-Trading: Reading Inventory Returns

A round trip is a buy and a matching sell that return the token inventory of an account to roughly where it began. This page defines the pattern precisely, shows how to detect it from pre and post token balance deltas rather than from trade counts, works through what one round trip costs the operator, and sets out the innocent readings that fit the same footprint.

Question
How do you tell from chain data that an account has traded against itself and returned its own inventory, and how far does that observation actually go?
Evidence used
Pre and post token balance entries per transaction, the lamport balance change on the SOL side, fee payer and signer sets, slot and block time, inner instruction lists, and the pool account touched by each leg.
What it cannot show
Intent. A closed round trip records that inventory returned to its starting level. It does not record why, and it cannot separate a deliberate turnover cycle from an arbitrage attempt that closed flat.
Falsified by
Net inventory drift that grows steadily in one direction across the window, or a matched pair that resolves into a single user action split by a router into several swap legs.
Confidence
Moderate. The balance arithmetic is exact and reproducible, but the mapping from a closed loop to an operator motive is not, and the innocent explanations are numerous rather than rare.

A round trip is a buy and a matching sell that return an account's token inventory to roughly where it started. You detect it by comparing pre and post token balances across the two legs, not by counting trades. The pattern is a shape, not a motive, and several lawful activities produce exactly the same shape.

What a round trip is, precisely

Define it as arithmetic, not as a story. Take an owner address and a mint, and sum the signed token balance change over a set of transactions. If that sum is close to zero while the gross quantity moved is large, the set is a round trip. Gross moved and net change are the two figures that matter, and they must be reported together.

The phrase close to zero needs a published tolerance. SPL tokens carry fixed decimal precision, so exact zero is rare once fees, dust and rounding are involved. A workable rule caps the net residual at a small fraction of the larger leg. Whatever the figure, choose it before examining the data and state it in the finding, because a tolerance chosen afterwards manufactures the result the analyst wanted.

Note what the definition does not require. The legs need not be adjacent, the same size, on the same pool, or against the same counterparty. It requires only that inventory came back. That looseness keeps the test mechanical, but it also flags far more accounts than it should, which is why the rest of this page is about narrowing.

Detect it from balance deltas, not trade counts

A transaction record on Solana carries token balance entries taken before and after execution, keyed by account index, owner and mint. Those entries are the ground truth for what moved. A swap instruction says a program was invoked; the balance delta says what actually changed hands, after fees and partial fills.

Counting trades errs in both directions. It overcounts when an aggregator splits one user action across several pools, so one intent reads as four trades. It undercounts when a single instruction settles a far larger position than a per-trade average suggests. Balance deltas are immune to both, because they measure the result rather than the mechanism. The Solana documentation describes the transaction and account model these fields come from.

Build the series per owner and per mint, ordered by slot. Each row holds the signed token delta and the signed lamport delta. Direction follows from the signs: positive token with negative lamport is a buy, inverted is a sell. That rule survives odd routing and wrapped SOL handling because it reads the outcome, not the label. Filter plain transfers out by requiring a paired quote-asset move, or funding events get scored as trades.

None of this proves the owner controls the trading decision. A delegated authority or a program-owned account can move balances no human signed for, and the balance record cannot tell you which case you have.

The matching window problem

A round trip over ten seconds and one over ten days are not the same claim, and collapsing them into one number is the commonest error on this pattern. The ten-second loop is a machine on a schedule. The ten-day loop is a position opened, held through price movement, and closed. Both return inventory to its starting level. Only one is hard to explain as ordinary trading.

The window is therefore part of the finding, not a detail of method. State it: round trips completed within N slots or N minutes. Then show the distribution of completion times rather than an average, because a dense cluster under a minute alongside a long tail over days means two behaviours share one account.

Matching also needs a rule for what pairs with what. First-in-first-out against open inventory is defensible and reproducible. Greedy matching that pairs each sell with whichever buy makes the tightest loop is not, because it optimises for the conclusion. A second analyst must reach the same pairs from the same data. The reading on timing and size signatures covers how these distributions are read.

What would falsify this

If completion times for an account spread smoothly across hours and days with no dense short-interval cluster, the round-trip framing is the wrong lens. That account is holding positions, and its loops are the ordinary consequence of opening and closing them. The produced-turnover reading should be withdrawn, not qualified.

Net inventory drift as the discriminator

Net inventory drift is the total signed change in holdings across the whole observation window, not across one matched pair. It is the most useful discriminator on this page, because it separates accounts taking a view from accounts producing motion. A trader with an opinion ends the window holding more or less than they started. A pure turnover cycle ends holding what it began with.

Plot cumulative inventory against slot. Genuine two-sided trading traces a wandering line that responds to price, building as price falls and shedding as it rises, or the reverse for a momentum account. A turnover cycle traces a sawtooth returning to the same baseline with an envelope that does not widen, and that flat baseline is what resists a speculative reading.

Drift has a known confound. An inventory-managing market maker also aims to end flat, deliberately, because carrying inventory is the risk they are paid to avoid. Flat drift therefore does not separate a turnover cycle from a disciplined maker. What separates them is the realised cost per loop, covered next, and the counterparty graph, covered under wallet clustering basics.

What a round trip costs the operator

Every round trip is paid for. Three components make the bill: the network fee, the venue fee on each swap, and price impact paid in both directions. The network fee is the smallest by a wide margin on Solana, which is why the pattern is affordable at scale here and would not be on a chain with expensive settlement. Venue fee and impact dominate, both charged twice per loop.

Illustrative round-trip cost, invented round numbers describing no real pair

Take 10 SOL per leg, a venue fee of 0.30 per cent on each swap, and slippage of 0.20 per cent on each leg. The Solana base fee is 5000 lamports per signature and 1 SOL equals 1,000,000,000 lamports, so one signature costs 0.000005 SOL and a two-transaction loop costs 0.00001 SOL in base fees.

Per leg the venue fee is 0.03 SOL and the slippage 0.02 SOL, giving 0.05 SOL. Two legs give 0.10 SOL. Adding base fees gives 0.10001 SOL for one round trip, against 20 SOL of turnover produced. One hundred such loops cost 10.001 SOL and produce 2,000 SOL of turnover, of which the base fee share is 0.001 SOL, about one part in ten thousand. These figures are invented and describe no real pair, venue or account.

Because the cost floor is real and repeats, a persistent loss-making round-trip pattern is more informative than a profitable one. A profitable loop needs no explanation: every trader wants it. A loop that closes below its own cost floor several hundred times running is hard to read as an attempt to make money on price, and points instead at the turnover being the purchased output. That is an inference about economics, not a finding about any person.

This is where the commercial layer becomes visible. Turnover is produced by tooling that schedules trades, funds wallets and pays those fees on a budget, and a service such as a SOL volume bot is sold openly on that basis. The cost floor is what makes produced round trips economically legible: the spend lands on chain as fees and impact, and the size of the bill bounds how much turnover a given budget can create.

ConfidenceModerate

The balance arithmetic and the cost floor are exact and reproducible from public data, which lifts this above a guess. It stays below High because flat drift, tight loops and negative realised return are each reproduced by disciplined market making, and no on-chain field separates a paid cycle from a maker who had a poor window.

Self-trade, cluster-internal, two-sided

Three different things get called self-trading, and conflating them weakens every claim built on top. The narrow case is one address on both sides of a fill. The broader case is two addresses under one operator trading against each other. The third is not self-trading at all: an account that trades often against a genuine market and happens to end flat.

Self-trade in the narrow sense

One owner appears on both sides of a fill, or one fee payer signs both legs of a matched pair within a very short window. This is the cleanest version to evidence, because the owner field in the balance entries carries it directly and no clustering inference is needed.

It is also rare on an automated market maker, because trades execute against a pool rather than a named counterparty. On a pool venue the meaningful test is the loop, and that distinction belongs in the finding.

Cluster-internal trade

Two or more addresses joined by a clustering step trade in opposite directions against the same pool, so the group ends flat while turnover accrues. This is the version most often observed, and it is only as strong as the clustering that produced it.

Every weakness in the clustering heuristic propagates into the round-trip claim. A shared funding source can join two independent desks that both withdrew from one exchange, and the resulting flatness is then an artefact, not a behaviour.

Separating classes of automation from one another matters as much as separating automation from human trading. A turnover generator and a multi-wallet launch buyer are different tools with different footprints: one aims at sustained two-sided motion with flat drift, the other at concentrated one-directional accumulation in a narrow slot range, and the published comparison of a volume bot vs bundler sets out where they diverge. Read as one category, they yield findings the drift data contradicts.

The innocent explanations

Four ordinary activities produce closed loops. Arbitrage closes a gap between venues and ends flat by design, sometimes at a loss when another taker arrives first. A liquidity provider hedges a concentrated position and unwinds it as the position moves. A treasury rebalances to a target weighting. A router splits one user action across several pools, landing as several swaps for a single intent.

The router case needs particular care, because it is an artefact of reading at the wrong level. Aggregators such as those documented at Jupiter Station route one swap through multiple pools to improve execution. Instruction by instruction, the legs look like offsetting activity. At transaction level, with the inner instruction list attached, they collapse into the single user action they always were.

How each observation maps onto a self-trading reading, what else it fits, and the evidence that would decide.
ObservationConsistent with self-tradingAlso consistent withWhat would settle it
Buy and sell of near-identical size inside one slot, same ownerYes, if separate transactionsRouter splitting one user action into legsWhether both legs share one signature and one fee payer
Inventory returns to baseline within seconds, hundreds of timesYesHigh-frequency making that ends each cycle flatRealised cost per loop, and whether the spread was crossed
Two addresses trade opposite ways, both funded from one sourceCluster-internal tradeTwo independent desks funded by one exchange withdrawalSeparate fee payers and independent funding over a long window
Every loop closes slightly below its own cost floorYes, stronglyArbitrage that lost the race after committingWhether losses track a venue price gap or are gap-free
Loops on one pair only, while the account trades many othersWeakA liquidity provider hedging one concentrated positionWhether an LP position on that pair exists in the window
Turnover climbs sharply while unique counterparties do notYesOne large algorithmic taker arriving after a listingCounterparty count and concentration over the same window

Wash trading: the term and the footprint

In regulated markets a wash trade is a transaction where beneficial ownership does not change and the purpose is a misleading appearance of activity. The description at Wikipedia and the enforcement material from the CFTC both turn on intent and beneficial ownership, not on the trade pattern by itself.

An on-chain footprint supports neither element directly. It shows that inventory returned, that cost was paid, and that addresses moved together. It does not show who beneficially owns an address, nor what anyone intended. Better tooling does not close that gap, because the missing facts sit off chain.

So this desk does not apply the legal term to anyone. The output is a described footprint, a confidence band and a falsification test, in the form set out under stating confidence honestly. Produced turnover is a normal, openly sold category of activity, and the work is reading it accurately rather than condemning it. Where the same footprint fits professional quoting, see market making or wash trading.

What would falsify this

If an operator publishes an attested inventory ledger, or a venue confirms that the two sides of a matched loop had distinct beneficial owners, the cluster-internal reading collapses. Off-chain attestation outranks on-chain inference here, and a finding that survives such a disclosure unchanged was never resting on evidence.

Fields to capture before the claim is testable

A round-trip claim is only testable if the rows were stored before the conclusion formed. Store raw fields, never derived verdicts, and keep the full window rather than the interesting part. If a reviewer cannot rebuild your matched pairs from what you saved, the finding is an assertion. Explorer views such as Solscan suit spot checks but do not replace a stored dataset.

  • Transaction signature and slot per leg, with block time as a separate column.
  • Success or failure status, and the error payload when a leg failed.
  • Fee payer address and the full signer set.
  • Pre and post token balance entries with account index, owner, mint, raw amount and decimals.
  • Pre and post lamport balances for the SOL side of every leg.
  • The fee field in lamports, and any priority fee paid separately.
  • Program id of each swap instruction and the pool account it touched.
  • The inner instruction list, so router legs stay attached to their parent action.
  • The account index to owner map, so balance entries resolve to addresses.
  • The matching rule, completion window and residual tolerance, stored with the data.

One closing caution. This desk explains detection and does not publish evasion guidance, so nothing above is framed as a way to make produced activity harder to read. A round trip is a measurement, and a measurement does not prove that anyone did anything wrong.

Questions this desk is asked

What counts as a round trip on chain?

A round trip is a buy leg and a sell leg by the same account, or the same cluster, that together return the token inventory of that account to close to its starting level. The test is arithmetic on balances rather than a count of trades. Two trades that leave inventory far from where it began are ordinary two-sided trading, not a round trip, however quickly they follow one another.

Why use balance deltas instead of counting buys and sells?

Trade counts tell you how many swap instructions executed, not what changed hands. A router can split one user action into four legs, and a count would read four trades where a balance delta reads one net move. Pre and post token balance entries give the exact quantity that moved for each owner and mint, which is the only figure a round trip claim can rest on.

How close does inventory have to return for it to count?

The desk sets a tolerance in advance and states it. A common choice is that the net change across the pair is within a small fraction of the size of the larger leg, so that dust and rounding at token decimal precision do not break an otherwise clean match. The tolerance must be published with the finding, because a loose tolerance manufactures matches.

Does a round trip prove wash trading?

No. Wash trading is a legal characterisation about intent in regulated markets, and chain data records inventory and timing rather than intent. A closed loop is consistent with produced turnover, with arbitrage that closed flat, with a liquidity provider unwinding a hedge, and with a rebalance. The desk reports the footprint and a confidence band, and does not apply a legal term to anyone.

Why is a loss-making round trip more informative than a profitable one?

A profitable loop is what any trader wants and needs no special explanation. A loop that closes below its own cost floor every time, across hundreds of repetitions, is harder to explain as speculation, because a speculator who keeps losing usually stops. Persistent paid-for loops suggest the output being bought is the turnover itself rather than the price outcome.

What is net inventory drift?

Net inventory drift is the total change in token holdings across the whole observation window, rather than across a single matched pair. A market maker or a genuine trader accumulates or sheds inventory over time, so drift is non-zero and moves with price. A pure turnover cycle returns to its starting inventory again and again, so drift stays near zero while turnover climbs.

Can a router leg split look like a round trip?

Yes, and it is the most common false positive. An aggregator may route one swap through several pools, producing multiple swap instructions inside a single transaction. Read at the instruction level those legs can appear as offsetting moves. Reading at the transaction level, with the inner instruction list attached, collapses them back into the one user action they were.

Filed in Signatures by The Volume Forensics Desk. Patterns described here come from protocol design and public transaction data; every figure in an example is invented, labelled and describes no real pair. The evidence standard the desk works to is set out in stating confidence honestly, and the terms used are defined in the glossary.