The same ETH can cost 1900 USDC on one exchange and 2100 USDC on another at the very same instant. That isn’t a glitch — it’s the default state of a world built from independent automated market makers. This lesson is about why that gap opens, exactly how much money sits inside it, and the deeply unintuitive reason you can’t just scoop up the whole thing.
Why two pools drift apart
Before you read — take a guess
Two different DEXes both let you swap ETH↔USDC. A big trader buys a pile of ETH on DEX A only. What happens to the ETH price on DEX B?
Picture two lemonade stands on opposite ends of a beach. They don’t share a till, a menu, or a manager. If a thirsty crowd swarms the north stand, its prices creep up; the south stand, oblivious, keeps selling cheap. Nothing connects them except your willingness to walk between them.
An automated market maker (AMM) is exactly that lemonade stand. Each pool holds two reserves — say ETH and USDC — and prices every trade off the constant-product invariant:
Here is the ETH reserve, is the USDC reserve, and is a constant the pool defends on every swap. The spot price of ETH (in USDC) is just the ratio of reserves:
Crucially, there is no shared order book across DEXes. Uniswap’s ETH/USDC pool and SushiSwap’s ETH/USDC pool are two separate piles of coins with two separate values. A swap on one pool changes only that pool’s reserves, and therefore only that pool’s price.
So when traders on different venues do their own thing — some buying on A, some selling on B — the two prices wander off in different directions. They diverge and stay diverged until someone deliberately trades the gap shut. That someone is an arbitrageur, and the gap is their paycheck.
Same asset, two prices, zero contradiction
There’s no arbitrage-free law being broken here. A price is just “what this specific pool charges given its current reserves.” Two pools with different reserves quote different prices for the same token — that’s arithmetic, not a market failure.
Match each piece of AMM plumbing to what it actually is.
Pick a term, then click its definition.
When it matters
Every time you see “the price of ETH,” ask whose price. On-chain there is no single number — there’s a price per pool, and the spread between them is the raw material of cross-DEX MEV. The bigger and more fragmented the liquidity, the more often these gaps appear.
Buy cheap, sell dear — the constant-product math
Before you read — take a guess
Pool A quotes ETH at 1900 USDC; Pool B quotes 2100 USDC. Ignoring price impact, what's the gross spread on flipping 1 ETH (buy on A, sell on B)?
Our two canonical pools:
| Pool | ETH reserve () | USDC reserve () | Spot price |
|---|---|---|---|
| A (cheap — buy here) | 100 | 190,000 | $1900 |
| B (dear — sell here) | 100 | 210,000 | $2100 |
The strategy writes itself: buy ETH where it’s cheap (A), sell it where it’s dear (B), pocket the difference. At the very first marginal unit, the math is gloriously simple — buy 1 ETH for $1900 on A, sell it for $2100 on B, and the gross spread is:
That “200 USDC for moving one token between two pools” is the headline number that makes arbitrageurs salivate. It’s also a lie of omission, because it assumes the prices don’t budge while you trade. They do. The island below lets you slide the arbitrage size and watch the naive spread get devoured by reality.
- Pool A price
- 1,999
- Pool B price
- 1,999
- Net profit
- 250.16
- USDC spent on A
- 4,872
- USDC from B
- 5,122
- optimum
- 2.5 ETH
The same trade that captures the spread is the trade that closes it. Pool A’s price climbs and pool B’s falls until they meet — and right where they meet, the profit peaks and then rolls over. Trade too big and you push the prices past each other and give the spread back.
Notice the left edge of the slider: at a tiny size, you really do capture roughly 200 USDC per ETH. The trouble starts the moment you get greedy.
Fill in the first-unit arbitrage.
Choose the correct option for each blank and check.
Buy ETH on the pool at 1900 USDC, sell on the dear pool at 2100 USDC, for a gross spread of on the first ETH — before bites.
When it matters
The naive spread tells you whether an opportunity exists; it never tells you how much you can extract. Confusing the two is how a bot “sees” a 200-USDC-per-ETH gap, fires a huge trade, and walks away with far less — or a loss. The real number always comes from the curve, never from the quote.
The trade moves the prices together
Before you read — take a guess
As you buy more and more ETH on the cheap pool A, what happens to A's quoted ETH price?
Here’s the twist that makes arbitrage self-extinguishing. When you buy ETH on A, you hand the pool USDC and take ETH out. A’s reserves shift: falls, rises, so its price climbs. When you sell that ETH on B, you do the reverse there: B’s rises, falls, so B’s price drops.
So the two prices march toward each other from both ends:
- Pool A (started at 1900): walks up as you buy.
- Pool B (started at 2100): walks down as you sell.
Keep going and they meet in the middle — at roughly 1999 USDC for the trade sizes around our optimum. The visual below shows a single pool climbing its own curve as you sell tokens into it; the spot price (the slope of the line from the origin) steepens with every unit.
- X sold in
- 0
- Y received out
- 0
- Old spot price
- 2,000
- New spot price
- 2,000
Sell ETH into a pool and you slide along the x·y = k hyperbola: the ETH reserve drops, the USDC reserve rises, and the spot price (the reserve ratio) shifts with every unit. In arbitrage, pool A climbs this way while pool B slides the other — until they meet.
The profound bit: the act that captures the spread is the act that closes it. You don’t arbitrage a gap and then watch it vanish — your own trade is the vanishing. Push enough volume through and the two pools quote the same price, the gap is gone, and there’s nothing left to capture. Arbitrage is a snake eating its own tail.
The gap is a melting ice cube
Every unit you trade shrinks the remaining spread. So the marginal profit per ETH is highest on your first unit and falls toward zero as you continue. If you size your trade as if all units earned the full 200-USDC gap, you’ve badly overcounted — the back of your trade earns almost nothing.
As you run the arbitrage (buy on A, sell on B), sort what happens to each pool's price.
Place each item in the right group.
- The pool whose ETH reserve is growing
- Pool B (the dear pool you sell into)
- The pool whose ETH reserve is shrinking
- Pool A (the cheap pool you buy from)
When it matters
This convergence is why no one stays rich off a single gap forever, and why the first bot to a discrepancy gets the cream. By the time the second arbitrageur arrives, the first one’s trade has already flattened most of the spread. Speed and ordering — the heart of MEV — exist precisely because the opportunity self-destructs on contact.
Why the optimal size is finite
Before you read — take a guess
If each extra ETH closes the gap a little, what does total arbitrage profit look like as a function of trade size?
Now the punchline. Naively you’d think: 200 USDC of gross edge per ETH, and the pools hold 100 ETH each — so just trade a huge amount and get rich. Wrong. Because every unit you trade closes the gap, your marginal profit per ETH falls as you go. Eventually it hits zero (the prices have met). Push past that and the prices cross — you’re now buying on the pool that’s become expensive and selling into the one that’s become cheap. You start handing the spread back.
That makes total profit hump-shaped in trade size: rising, peaking, then falling. For our canonical pools the peak sits at about 2.5 ETH, netting roughly 250 USDC:
| Arbitrage size | A’s price after | B’s price after | Net profit |
|---|---|---|---|
| 0.5 ETH | ~$1929 | ~$2069 | ~$70 |
| 1.5 ETH | ~$1959 | ~$2040 | ~$190 |
| 2.5 ETH (optimal) | ~$1999 | ~$1999 | ~$250 |
| 4.0 ETH | ~$2061 | ~$1938 | ~$210 |
| 6.0 ETH | ~$2133 | ~$1872 | ~$60 |
Read the table top to bottom: profit climbs to its $250 peak at 2.5 ETH — exactly where the two prices kiss at ~1999 USDC — and then declines even though you’re trading more. By 6 ETH you’ve shoved A’s price clean above B’s and given most of the edge back.
What sets the cap is depth — how much liquidity each pool holds. Deeper pools (bigger reserves) move less per unit traded, so the gap closes slowly and the optimal trade is larger. Shallow pools impact-out almost immediately, so even a tiny arbitrage exhausts the edge. The optimum is wherever the marginal profit of one more ETH hits zero — not “as big as the reserves allow.”
'As big as possible' is the rookie's ruin
Maximizing trade size does not maximize profit — it maximizes price impact. Past the optimum you’re paying to undo your own edge. The right size is the one where the next ETH would earn zero, and that’s usually a small fraction of the pool.
An arbitrageur could trade 2.5 ETH (net ~250 USDC) or 6 ETH (net ~60 USDC) across our two pools. Why is the smaller trade more profitable?
When it matters
Sizing is the strategy. Two bots see the identical 200-USDC gap; the one that solves for the hump’s peak — and stops there — out-earns the one that fires the biggest possible trade. In the next lessons this exact “find the optimum, then race to land it first” problem is what the whole MEV supply chain is built around.
Recap
Big picture
Cross-DEX price discrepancies, in one map
- Cross-DEX gaps
- Why they open
- No shared order book
- Each pool prices off own reserves
- A trade moves only that pool
- The naive edge
- Buy cheap on A 1900
- Sell dear on B 2100
- Gross spread 200 per ETH
- Self-extinguishing
- Buying walks A up
- Selling walks B down
- Converge near 1999
- Optimal size finite
- Profit is hump-shaped
- Optimum near 2.5 ETH
- Net about 250 USDC
- Depth sets the cap
- Why they open
Cross-DEX discrepancies — final check
Why can the same ETH quote 1900 USDC on one DEX and 2100 on another at the same moment?
Check your answer to continue.