mev
sandwich-attack
uniswap

Sandwich Attacks and MEV: Why Your DeFi Users Are Getting Robbed On Every Swap

$1.3 billion extracted from DeFi users through MEV in 2023 alone — and most of the victims had no idea it was happening. Sandwich attacks are the silent tax on every swap your users make. If you're building a DEX, a router, or any protocol that touches Uniswap pools, this is the vulnerability you're probably shipping right now.

Updated October 4, 2026
Duron Epps, Founder
14 min read
Share:X / TwitterLinkedIn

$1.3 billion extracted from DeFi users through MEV in 2023 alone — and most of the victims had no idea it was happening. Not a rug pull. Not a hack. Just bots watching the mempool, jumping in front of your transaction, and taking a cut before your swap even executes. Sandwich attacks are the silent tax on every trade your users make, and if you're building anything that touches an AMM, you're either protecting against this or you're complicit in it.

Here's What Actually Happens in a Sandwich Attack

Your user submits a swap on Uniswap — say, 10 ETH for USDC. That transaction sits in the public mempool for a moment before it gets included in a block. MEV bots are watching every pending transaction in real time.

The bot sees the trade. It calculates exactly how much slippage your user is willing to accept. Then it does two things in rapid succession:

  • Front-run: The bot submits its own buy transaction with a higher gas fee, getting included in the block first. This pushes the price up.
  • Back-run: Immediately after your user's trade executes at the inflated price, the bot sells — pocketing the difference.

Your user gets their USDC. Just less of it than they should have. The bot walks away with the spread. This happens thousands of times per day across every major DEX.

The most infamous large-scale MEV event was the c0re.finance exploit in 2020, where a single bot extracted roughly $130,000 in a single block reorg-assisted sandwich. But the real damage isn't in headline numbers — it's the cumulative drain. Flashbots' own data shows MEV bots have extracted over $680M from Ethereum users through sandwich attacks specifically, with the pace accelerating as bots get smarter.

The Real Killer Isn't What You Think

Everyone in DeFi talks about reentrancy. It's the vulnerability that gets the war stories. But sandwich attacks and MEV extraction don't require a contract bug at all — they exploit economic design decisions you made when you set default slippage parameters. That's what makes them so dangerous for developers to reason about.

Most audits check your contract logic. Almost none of them model the economic environment your contract operates in. A contract can be logically perfect and still bleed your users dry because it defaults to 1% slippage tolerance on a volatile asset pair, or because it lets users set slippage to 49% to avoid failed transactions on a busy network.

The vulnerability isn't always in your code. Sometimes it's in your UX defaults.

The Code Reality: What Vulnerable Looks Like

Here's the pattern I see constantly in DEX aggregators and custom swap routers. A function that calls Uniswap V2 or V3 with user-specified slippage but no meaningful floor:

// Solidity 0.8.24 — VULNERABLE PATTERN
// No minimum output floor, slippage tolerance unchecked

function swapExactTokensForTokens(
    uint256 amountIn,
    uint256 amountOutMin,  // User-supplied — could be 0
    address[] calldata path,
    address to,
    uint256 deadline
) external returns (uint256[] memory amounts) {
    // Problem: amountOutMin is passed through with zero validation
    // If the frontend sends 0 or near-zero, user is fully exposed to sandwich
    
    IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn);
    IERC20(path[0]).approve(UNISWAP_ROUTER, amountIn);
    
    amounts = IUniswapV2Router02(UNISWAP_ROUTER).swapExactTokensForTokens(
        amountIn,
        amountOutMin,  // Bot can sandwich freely if this is too low
        path,
        to,
        deadline
    );
    
    return amounts;
}

This function will execute a swap with amountOutMin = 0 if the caller passes it. That means a sandwich bot can push slippage to 99% and the transaction still goes through. Your user loses almost everything. The contract doesn't revert. No error. Just a terrible price.

Here's how you fix it — enforce a protocol-level minimum slippage cap and validate deadline aggressively:

// Solidity 0.8.24 — PROTECTED PATTERN
// OpenZeppelin 5.x for access control if needed

error SlippageTooHigh(uint256 provided, uint256 maxAllowed);
error DeadlineTooFar(uint256 provided, uint256 maxAllowed);
error AmountOutMinTooLow(uint256 provided, uint256 minRequired);

uint256 public constant MAX_SLIPPAGE_BPS = 100; // 1% max slippage, configurable
uint256 public constant MAX_DEADLINE_DELTA = 20 minutes;

function swapExactTokensForTokensSafe(
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    address to,
    uint256 deadline
) external returns (uint256[] memory amounts) {
    
    // Validate deadline — long deadlines increase sandwich window dramatically
    if (deadline > block.timestamp + MAX_DEADLINE_DELTA) {
        revert DeadlineTooFar(deadline, block.timestamp + MAX_DEADLINE_DELTA);
    }
    
    // Get expected output from oracle or pool quote
    uint256 expectedOut = _getExpectedOutput(amountIn, path);
    
    // Enforce minimum slippage floor — user can't set below protocol minimum
    uint256 minAcceptableOut = expectedOut * (10000 - MAX_SLIPPAGE_BPS) / 10000;
    
    if (amountOutMin < minAcceptableOut) {
        revert AmountOutMinTooLow(amountOutMin, minAcceptableOut);
    }
    
    IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn);
    IERC20(path[0]).approve(UNISWAP_ROUTER, amountIn);
    
    // Use the higher of user-specified or protocol minimum
    uint256 effectiveMinOut = amountOutMin > minAcceptableOut 
        ? amountOutMin 
        : minAcceptableOut;
    
    amounts = IUniswapV2Router02(UNISWAP_ROUTER).swapExactTokensForTokens(
        amountIn,
        effectiveMinOut,
        path,
        to,
        deadline
    );
    
    return amounts;
}

function _getExpectedOutput(
    uint256 amountIn, 
    address[] calldata path
) internal view returns (uint256) {
    // Use a TWAP oracle here in production — spot price is manipulable
    // Uniswap V3 provides on-chain TWAP via observe()
    uint256[] memory amounts = IUniswapV2Router02(UNISWAP_ROUTER)
        .getAmountsOut(amountIn, path);
    return amounts[amounts.length - 1];
}

Two additional things that matter here: First, using spot price from getAmountsOut in production is still somewhat gameable — a TWAP oracle (Uniswap V3's built-in observe() function is solid) gives you a price that's much harder to manipulate within a single block. Second, that deadline parameter is often overlooked. A 10-minute deadline dramatically shrinks the window where a queued transaction can be sandwiched compared to a 24-hour deadline that some frontends default to.

How I'd Catch This Before It Ships

When I'm reviewing a swap router for MEV exposure, I'm not just looking for missing require statements. I'm modeling the economic attack surface. Here's my actual checklist:

1. Trace every path where amountOutMin reaches the actual swap call. Can it be zero? Can it be set by an untrusted caller? Can the frontend override a contract-level minimum? Follow the data all the way down.

2. Check deadline handling. Search the codebase for every instance of deadline being passed to a Uniswap call. Is there a maximum enforced? I've seen production routers that accept type(uint256).max as a deadline — that's an open invitation to every MEV bot watching the mempool.

3. Look for TWAP vs. spot price usage. If the contract derives expected prices from spot state in the same block as the swap, that price can be manipulated by a flash loan before the user's transaction. Uniswap V3's TWAP is the standard mitigation here.

4. Test economic scenarios, not just logic paths. Run simulations: what happens to users in this contract if a bot can control transaction ordering? What's the maximum extractable value at various slippage settings? Most static analyzers won't tell you this — it requires thinking about the contract as an economic actor, not just a state machine.

5. Check if private mempool submission is possible. If your protocol is serious about MEV protection, consider integrating with Flashbots Protect RPC or similar private transaction relays at the UI layer. That's not a contract fix — it's an architecture decision, but it matters more than most contract-level mitigations for liquid protocols.

Beyond Sandwiches: The Broader MEV Problem

Sandwich attacks are the most visible MEV strategy, but they're one piece of a larger picture. Liquidation front-running, arbitrage extraction, and JIT (just-in-time) liquidity attacks all operate on similar principles — bots with better information and faster reaction times extracting value from your users' pending transactions.

The Euler Finance hack in March 2023 ($197M stolen and later mostly returned) had an interesting MEV dimension: within minutes of the attack transactions hitting the mempool, arbitrage bots had extracted additional value from the price dislocations caused by the exploit. Even in the chaos of a hack, MEV bots are running their playbook. That's how ingrained this is in the current Ethereum execution environment.

EIP-1559 changed gas dynamics but didn't solve MEV. PBS (Proposer-Builder Separation) has shifted who captures MEV value but hasn't eliminated it for users. The honest answer is that MEV is a permanent feature of any public mempool-based blockchain, and protocol design needs to account for it as a constant adversarial pressure — not a bug to be patched eventually.

Static Tools vs. Economic Analysis

Static analysis tools like Slither will catch obvious slippage validation bugs if the pattern is simple enough. But they won't catch a case where your contract correctly validates that amountOutMin > 0 while missing the fact that 1 wei is a practically zero floor on a 10 ETH swap. They can't model the game theory of block ordering or identify that your default slippage settings in the accompanying frontend create the real exposure.

That's where AI-powered contract analysis earns its keep — understanding the contract in context, flagging not just logic errors but economic design patterns that create MEV exposure. Run your contract through SmartContractAuditor.ai before you deploy. It flags exactly this type of slippage and deadline misconfiguration, explains why it's dangerous in plain terms, and gives you a prioritized list of what to fix — not just a list of warnings to decipher.

Five Specific Things to Do Right Now

  1. Search your codebase for every amountOutMin or minAmountOut parameter and trace whether a zero or near-zero value can reach an actual swap execution. If it can, add a protocol-enforced floor.
  2. Audit your deadline handling — grep for every Uniswap router call and verify there's a maximum deadline delta enforced on-chain, not just in the frontend.
  3. Replace spot price queries with TWAP wherever you're using on-chain price data to calculate expected outputs. Uniswap V3's observe() function with a 30-minute window is a reasonable starting point.
  4. Test with a Flashbots simulation environment — tools like mev-inspect-py can show you what MEV extraction looks like against your specific contract logic before real money is at stake.
  5. Paste your contract into SmartContractAuditor.ai before you deploy — it takes 30 seconds and it'll flag slippage misconfigurations, deadline issues, and economic attack vectors that Slither alone will miss.

Your users are trusting you with real money. Every swap they make through your protocol is either protected or it's prey. There's no middle ground in a public mempool.

Further Reading

Related Articles

Continue exploring smart contract security with these related insights

uniswap
defi

Uniswap V4 Security Guide: Hooks, Pools, and New Attack Vectors You Need to Know Before Deploying

Uniswap V4 hooks are the most powerful — and most dangerous — primitive in AMM history. One malicious or misconfigured hook can drain an entire pool in a single transaction. Here's what every developer and DeFi user needs to check before touching V4.

36 views
Read Article
Published on
June 22, 2026