Standard Attack Patterns: Sandwich, Back-Running, JIT
Most MEV extraction falls into a small number of well-understood patterns. Auditors should be able to recognize each on sight and identify the contract-level conditions that enable them.
Sandwich Attacks
The most common public-mempool MEV pattern, applied primarily to AMM swaps.
Mechanics:
- Victim broadcasts a swap on a public AMM (e.g., Uniswap V2): sell 100 ETH for USDC, with slippage tolerance 1%.
- Searcher observes the pending transaction and computes that, with current pool reserves, this swap will move the price by 3%.
- Searcher constructs a bundle:
- Transaction A (front-run): searcher sells ETH for USDC, pushing the price down to just within the victim's slippage tolerance.
- Transaction B (victim's, unchanged): executes at the worse price.
- Transaction C (back-run): searcher buys ETH back from the pool, capturing the price difference.
- Bundle is submitted to a builder; if it wins block inclusion, the searcher profits the price movement minus gas and validator payment.
The victim receives no error. Their swap executes within their stated slippage tolerance. They simply receive the worst-case amount their slippage allowed.
Contract-level enabling conditions:
- A constant-product AMM (or any pool with predictable price impact).
- A swap that has price impact larger than the slippage tolerance + gas costs.
- Public mempool submission.
Mitigations at the contract level:
- Tight slippage tolerance. Setting
minAmountOutclose to the expected output (e.g., 0.1% rather than 1%) limits the searcher's profit window. This is a user-side mitigation but contracts can encourage or enforce it. - Deadline parameters. A short
deadlinereduces the window during which the transaction can be sandwiched, but does not eliminate it. - Frequent batch auctions (CowSwap model). Users submit intents that are batched and matched off-chain at a uniform clearing price, eliminating per-transaction price impact entirely.
- Private-mempool submission. Hides the transaction from public searchers; described in §4.13.4.
- Sealed-bid mechanisms. Hide the swap parameters at submission time (commit-reveal); described in §4.13.3.
Audit notes:
- A swap function with a
minAmountOutparameter is necessary but not sufficient; the parameter must actually be enforced (require(out >= minAmountOut)after the swap). - A swap function without a
minAmountOut(or equivalent) is a critical finding: users have no defense. - A
minAmountOutparameter that defaults to 0 in any helper or router contract is a critical finding.
Back-Running
Less hostile than sandwiching, but still a form of value extraction.
Mechanics:
- Victim's transaction moves the state in a way that creates a profitable opportunity (e.g., a large swap leaves a price imbalance against another DEX).
- Searcher submits a transaction immediately after the victim's, capturing the arbitrage.
Back-running typically does not worsen the victim's outcome. The price they receive is the same as if they had been the only transaction. The searcher captures value that would otherwise go to a (possibly more sophisticated) arbitrageur in a later block.
MEV-Share (§4.13.4) lets users monetize back-running: the protocol shares the fact that a back-runnable transaction is coming, searchers compete to back-run it, and a portion of their profit is rebated to the user. This is sometimes a net positive for users compared to public-mempool submission.
Audit relevance: Lower than sandwiching, but worth flagging when a contract creates large, predictable arbitrage opportunities (e.g., a rebase that leaves a stale price in a pool). Users may want to be informed that their interaction is reliably back-run.
Just-in-Time (JIT) Liquidity
A specialized pattern targeting concentrated-liquidity AMMs (Uniswap V3 and similar).
Mechanics:
- Searcher observes a large incoming swap in the mempool.
- Same block, just before the swap, searcher deposits a large concentrated-liquidity position into the price range the swap will cross.
- Swap executes; searcher's position captures most of the LP fees.
- Same block, just after the swap, searcher withdraws the position.
The searcher earns the LP fee from the large swap without holding the position before or after. Existing LPs in that range earn proportionally less.
Who is harmed: Existing concentrated LPs see their fee income reduced. The swapper themselves is usually unaffected (the swap executes at the same price they expected).
Mitigations: Mostly at the AMM design level (Uniswap V4 hooks can implement anti-JIT logic). At the audit level, JIT is rarely a "finding" against the AMM itself but is worth understanding when reviewing LP strategies.
NFT Mint Sniping
Mechanics:
- NFT contract launches a public mint with a fixed price below the expected market value (an underpriced mint).
- Bots monitor pending
mint()transactions and either race to mint first or back-run mints by listing on a marketplace at a markup. - Genuine users are crowded out by bots that pay higher gas.
Mitigations:
- Allow-lists restrict who can mint.
- Sealed-bid or auction-based pricing (rather than fixed-price mints) lets the market discover the clearing price without rewarding gas wars.
- Dutch auctions front-load price and reduce the incentive to race.
Audit relevance: Worth raising when a contract has a fixed-price launch mechanism whose expected market value exceeds the mint price. The launch mechanic is itself a finding because users are not the actual beneficiaries.
Liquidation Sniping
Mechanics:
- A lending position becomes liquidatable (health factor crosses 1).
- Multiple bots see the opportunity simultaneously and race to call
liquidate(). - Gas auction drives the searcher's profit to (reward - gas paid), with most of the value going to validators.
This is generally good for the protocol (positions get liquidated quickly), neutral for the borrower (someone was going to liquidate them anyway), and the only "loser" is the searcher who didn't win the race.
Audit notes:
- Liquidation incentives should be sized to ensure liquidations happen fast enough to keep the protocol solvent under stress. Too low an incentive risks insolvency; too high transfers value from borrowers to liquidators unnecessarily.
- "Liquidation cliffs" — discontinuous jumps in collateral seizure — create perverse incentives for the borrower and the liquidator.
- Some protocols use Dutch-auction liquidation (Liquity-style) to reduce gas wars by letting the bonus discover its market level over time.
Oracle Update Sandwiching
Mechanics:
- A protocol updates its on-chain oracle once per block, based on TWAP or external data.
- Searcher observes the upcoming oracle update (e.g., a Chainlink price post hitting the mempool).
- Searcher front-runs the oracle update with a transaction that benefits from the old price (e.g., opening a leveraged position), then back-runs the update with a closing transaction at the new price.
The protocol's users absorb the price impact; the searcher captures the difference.
Mitigations:
- Push oracle updates and dependent actions atomically so they cannot be sandwiched in the same block.
- Use pull-based oracles with attestation (Pyth model, Chainlink Data Streams), where the price proof and the dependent action are bundled into the same transaction by the user.
- Apply a TWAP or moving average to dampen instantaneous-price exposure.
Audit notes: Any contract that observes an oracle and immediately acts on it in a way that profits from the new value is a candidate for this attack. The fix is design-level, not parameter-level.
Sniping Time-Sensitive Functions
Any function that becomes callable at a specific block (vesting unlocks, governance executions, scheduled rebases) and pays the caller a reward gets sniped by searchers. This is usually not a problem if the design accounts for it, but:
- A function whose reward is meant for the protocol's users but ends up captured by random bots is mis-designed. Distribution mechanisms (claim windows, allow-listed callers, batched callers paid pro-rata) help.
- A function whose execution must happen "as soon as possible" usually benefits from being snipeable: the protocol gets execution quickly, the cost is just paying a small reward to the snipe-winner.
A General Heuristic
For any function that:
- Reads a price or quantity from on-chain state, and
- Causes a state change whose value depends on that price/quantity,
ask: what does the value of the action look like as a function of the difference between the price observed and the "true" price? If the answer is a step function or has a sharp gradient, the function is sandwich-able or sniped. If it is a small, gradual function, MEV exposure is bounded.
This heuristic catches most MEV-prone contract designs and is worth applying mechanically during code review.