You’ve seen what MEV is and how the orderflow auction decides who gets to sit where in a block. Now meet the attack that put MEV on the map — the one that taxes ordinary DeFi traders thousands of times a day, mechanically, with surgical precision. It’s called a sandwich, and once you’ve seen the constant-product math, you’ll never look at a pending swap the same way again.
The whole thing rides on a single fact you already know: a swap on an automated market maker (AMM) moves the price. The pool sits on the curve , and every trade walks it along that curve. The attacker’s entire trick is to move the price before you, so you fill at a worse spot, then move it back after you, banking the gap. Your loss is, almost to the penny, their gain.
Before you read — take a guess
What is a sandwich attack, in one sentence?
The anatomy: buy, let them fill, sell — in one block
Analogy. Picture a concert ticket scalper standing by the box office. The instant they see you walk up to the queue, they sprint to the window, buy every front-row seat, and watch the price tick up as the good seats vanish. You reach the window, find only the now-pricier seats left, and grudgingly buy. The moment your money clears, the scalper turns around and resells their hoard into the demand they just manufactured. They were never going to the concert. They were going to you.
Definition. A sandwich attack is a three-transaction MEV strategy executed within a single block, in this exact order:
- Front-run — the attacker, seeing the victim’s pending swap, buys the same asset first, pushing the spot price up.
- Victim swap — the victim’s transaction now executes against the worsened pool and receives fewer tokens than they would have unmolested.
- Back-run — the attacker immediately sells back exactly what they bought, into the price the victim’s own trade just propped up. The difference, minus fees, is profit.
The “in one block, in that order” part is non-negotiable. The attacker pays for that ordering — through priority fees or a direct bid to the block builder — which is precisely the MEV-auction machinery from the previous lessons. A sandwich is just an ordering preference with a profit motive attached.
The victim isn't a whale being targeted personally
A common misconception: “sandwiches only hit huge, careless trades.” Not so. Bots scan the public mempool for any swap whose size and slippage tolerance leave room for profit — a routine $2,000 token buy is fair game. It’s not personal and it’s not rare; it’s an automated tax on visible orderflow. The defense isn’t being small, it’s being unpredictable (private orderflow) or leaving no room (tight slippage).
Why it works: a market order moves the price, slippage tolerance makes you fillable
Analogy. Slippage tolerance is the blank space you leave on a signed cheque. Set it to 0.5% and you’ve told the pool, “fill me as long as I get within 0.5% of the quote — otherwise tear it up.” Set it to 20% and you’ve signed a cheque with a huge blank space, and you’ve invited anyone watching to fill in a number right up to the limit. The attacker reads that limit straight off your transaction and pushes the price to the very edge of it.
Here’s the chain of cause and effect:
- A swap on an AMM is a market order — it walks the curve, and bigger orders walk further, so the average price you fill at gets worse the more you buy. (This is exactly the price-impact curve from the AMM lessons.)
- The attacker’s front-run buy moves the pool up the curve first, so when your swap lands, it starts from a worse spot price than the one you saw when you signed.
- Your transaction still goes through — because of your slippage tolerance. You authorized a fill anywhere down to
spot × (1 − tolerance). The attacker’s job is to shove the price as close to that floor as they can without crossing it.
So slippage tolerance is the whole ballgame:
- Tolerance too high → a fat sandwich. You’ve authorized a big price move, so the attacker can front-run aggressively and still leave your trade fillable. More room = more extractable profit.
- Tolerance too low → the attack fails. If the attacker’s front-run pushes the price past your floor, your swap reverts (it can’t fill within tolerance), the attacker is left holding tokens with no victim to sell into, and they eat the loss. A trade that reverts pays no sandwich.
The curve below is the price-impact relationship the attacker is exploiting. Notice how a tight slippage tolerance (the dashed guardrail) cancels trades that would fill too far from quote — that same guardrail is what protects you from a sandwich.
Pool depth
- Spot price
- $2,000.00
- Avg execution price
- $1,818.18
- Price impact
- 9.09%
- You receive
- $18,181.82
- Minimum received
- $19,900.00
- Slippage tolerance
- 0.5%
⚠ Exceeds slippage tolerance — trade would revert
A swap walks the x·y=k curve, so the average fill price worsens as the trade grows — that's the price impact a sandwich manufactures by going first. The dashed line is your slippage tolerance: drop it and the trade reverts rather than filling far from quote, which is exactly what starves an attacker of a sandwich.
Spot the trap. A trader sets a 15% slippage tolerance on a token swap to 'make sure it goes through.' Why is this dangerous?
The exact math, worked
Let’s compute a real sandwich on a clean pool, no fees, so every digit is traceable. This matches the interactive defaults below exactly.
Setup. A constant-product pool holds ETH and USDC, so the invariant is
The starting spot price is USDC per ETH. The victim wants to spend $20,000 buying ETH. The attacker also front-runs with $20,000.
The two formulas we need (buying ETH with USDC, then selling ETH back for USDC), both straight from :
- Buy ETH: pay USDC into the pool; you receive ETH.
- Sell ETH: put ETH into the pool; you receive USDC.
Baseline — the victim alone, no attacker. The victim’s $20,000 hits the untouched pool:
So with no attack the victim gets 9.0909 ETH. Hold that number.
Step 1 — Front-run. The attacker buys first with $20,000, against the same untouched pool. The arithmetic is identical to the baseline, so the attacker receives ETH. The pool is now
New spot price: USDC/ETH. The price jumped from $2000 to $2420 before the victim’s trade even runs.
Step 2 — Victim swap. Now the victim’s $20,000 hits the worsened pool :
The victim gets only 7.5758 ETH — versus 9.0909 unmolested. The pool moves to
so the spot price is now USDC/ETH.
Step 3 — Back-run. The attacker sells back exactly the ETH they bought, into pool :
The attacker spent $20,000 and received $23,607, for a profit of ≈ $3,606. The back-run drops the price to roughly USDC/ETH — note it does not return to $2000, because the victim’s purchase permanently shifted the reserves.
Here is the whole sequence as a ledger of pool states and prices:
| Step | Reserves (ETH) | Reserves (USDC) | Spot price (USDC/ETH) | Who fills, and how much |
|---|---|---|---|---|
| Start | 100.0000 | 200,000 | $2,000 | — |
| After front-run | 90.9091 | 220,000 | $2,420 | Attacker buys 9.0909 ETH |
| After victim | 83.3333 | 240,000 | $2,880 | Victim buys only 7.5758 ETH |
| After back-run | 92.4242 | ≈217,393 | ≈$2,341 | Attacker sells 9.0909 ETH for ≈$23,607 |
The punchline. The victim lost ETH to the sandwich (worth about $3,030 at the $2000 start price). The attacker walked away with ≈ $3,606. The two numbers aren’t identical — fees, the asymmetry of the curve, and the back-run selling into a price the attacker’s own back-run depresses mean the attacker’s profit and the victim’s loss don’t tie out exactly — but the victim’s loss is the source of the attacker’s gain. Wealth was transferred, not created.
- Front-run
Attacker buys first, pushing the price up.
- Victim swap
Victim now buys at the worse price.
- Back-run
Attacker sells back, banking the difference.
Spot price across the sandwich
- Victim gets (no attack)
- 9.0909 ETH
- Victim gets (sandwiched)
- 7.5758 ETH
- Victim loses
- 1.5152 ETH≈ $3,030.30
- Attacker profit
- $3,606.56
The defaults here are the worked example exactly: a 100 ETH / 200,000 USDC pool, a $20,000 victim swap, a $20,000 front-run. Watch the price track $2000 → $2420 → $2880 → $2341 as the three trades land. The victim gets 9.0909 ETH alone but only 7.5758 ETH sandwiched — a 1.5152 ETH loss — while the attacker banks about $3,606. Drag the sliders: a smaller victim trade or a smaller front-run shrinks the bite.
Using the worked pool (100 ETH / 200,000 USDC, k = 2×10⁷), the victim would get 9.0909 ETH unsandwiched but only 7.5758 ETH after the front-run. What is the victim's loss?
Fill in the constant-product mechanics of the sandwich.
Pick the right option for each blank, then check.
A swap walks the pool along . The attacker's front-run the spot price before the victim fills, so the victim receives tokens. The attack only goes through because the victim's authorizes a fill at the worsened price; set it tight enough and the victim's trade , starving the attacker.
The attacker’s optimization: there’s a Goldilocks front-run size
The attacker doesn’t just pick any front-run size — there’s an optimal one, and both extremes leave money behind.
Analogy. Think of squeezing a sponge to wring out water. Squeeze too gently and water stays trapped (profit left on the table). Squeeze with your whole body weight and you’ve spent more effort than the last few drops are worth — and you might crush the sponge entirely (the victim’s trade reverts). There’s a sweet middle squeeze that extracts the most.
The trade-offs:
- Front-run too small → you barely move the price, the victim fills almost as well as they would have, and the gap you can harvest on the back-run is tiny. Profit left on the table.
- Front-run too big → two problems compound. First, you’ve bought a lot of ETH at progressively worse prices, and when you back-run you’re selling into a price your own back-run depresses (a large sell walks the curve back down), so your average exit is poor. Second, and worse, if your front-run pushes the spot price past the victim’s slippage floor, the victim’s trade reverts — and now you’re holding a big inventory of ETH with no victim to sell into, possibly at a loss.
So the optimal front-run is bounded above by the victim’s slippage tolerance: you push the price as far as you can without tripping the revert, and no further. The exact optimum has a closed-form solution in terms of the reserves and the victim’s size, but the intuition is what matters here — the profit-maximizing squeeze sits right at the edge of what the victim authorized. Crank the attacker slider in the widget above past a point and you’ll see the attacker’s profit fall, not rise: that’s the over-squeeze.
Cause and effect: an attacker keeps increasing their front-run size on a fixed victim trade. Beyond the optimal point, what happens to the attacker's profit, and why?
Defenses preview: starve the sandwich
You don’t have to be lunch. Every defense attacks one of the two ingredients a sandwich needs — visibility of your pending swap, or room in your slippage tolerance. We’ll give each a full treatment in the mitigations lesson, but here’s the map:
- Tighter slippage tolerance. Leave the attacker no room. A 0.1–0.5% tolerance on a liquid pair means the front-run can’t move the price far before your trade would revert — so there’s no profitable sandwich to make. The cost: legitimate volatility can revert your trade too.
- Smaller / split trades. A big order is a big, juicy target with lots of price impact to harvest. Splitting it into smaller pieces (or routing through deeper pools) shrinks the impact per fill and the profit available.
- Private orderflow / MEV-protect RPCs. If the attacker can’t see your pending swap, they can’t front-run it. Sending transactions through a private relay or an MEV-protected RPC keeps them out of the public mempool until they’re already in a block.
- MEV-aware routers. Modern routers split orders across pools, set sane default tolerances, and can route through private orderflow automatically — bundling several of the above into one click.
Big picture
Sandwich attacks — the whole mechanism
- Sandwich attack
- Anatomy (one block)
- 1. Front-run buy → price up
- 2. Victim fills at worse price
- 3. Back-run sell → bank the gap
- Why it works
- AMM swap walks x·y=k → price impact
- Front-run worsens the victim’s spot
- Slippage tolerance makes the victim fillable
- The math (worked)
- Pool 100 ETH / 200k USDC, k=2×10⁷
- Price $2000 → $2420 → $2880 → $2341
- Victim loses 1.5152 ETH
- Attacker profit ≈ $3,606
- Attacker optimization
- Profit is hump-shaped in front-run size
- Too big → bad exit + revert risk
- Bounded by victim’s slippage floor
- Defenses (preview)
- Tighter slippage tolerance
- Smaller / split trades
- Private orderflow / MEV-protect RPC
- MEV-aware routers
- Anatomy (one block)
Recap: sandwich attacks
Put the three transactions of a sandwich in the order they execute within the block.
Check your answer to continue.
You now understand MEV’s most notorious face — the predatory sandwich, worked out to the last decimal of . But not all MEV is theft. Next up, arbitrage and liquidations — the benign side of ordering, where the same speed-and-sequence game keeps prices consistent across venues and clears bad debt out of lending protocols. Same mechanics, very different ethics.