Best Practices

Frontrunning Protection: Building MEV-Resistant Smart Contract Patterns

Kennedy OwiroDecember 20, 20259 min read

If your smart contract handles value-sensitive operations — swaps, auctions, liquidations, or token launches — it's a frontrunning target. MEV bots monitor the public mempool, extract your transaction details, and exploit them before your transaction executes. Protection isn't optional; it's a design requirement.

Why Standard Transactions Are Vulnerable

Every pending Ethereum transaction sits in the public mempool, fully visible to anyone. MEV bots have millisecond-latency connections to nodes, sophisticated simulation engines, and direct builder relationships. If your transaction is profitable to frontrun, it will be.

Pattern 1: Commit-Reveal

Users first commit to an action (submitting a hash), then reveal it in a later block. Bots can't see the action during the commit phase.

// Phase 1: Commit (action hidden)
function commit(bytes32 commitment) external {
    require(commitments[msg.sender] == bytes32(0), "Already committed");
    commitments[msg.sender] = commitment;
    commitBlocks[msg.sender] = block.number;
}

// Phase 2: Reveal (after 1+ blocks)
function reveal(uint256 amount, uint256 price, bytes32 salt) external {
    require(block.number > commitBlocks[msg.sender], "Too early");
    require(block.number <= commitBlocks[msg.sender] + 100, "Expired");
    require(
        keccak256(abi.encode(amount, price, salt)) == commitments[msg.sender],
        "Invalid reveal"
    );
    delete commitments[msg.sender];
    _executeOrder(msg.sender, amount, price);
}

Pattern 2: Batch Auctions

Instead of processing orders sequentially (exploitable), batch all orders submitted during a time window and settle them at a uniform clearing price. CoW Protocol and Gnosis Auction use this approach.

Pattern 3: Private Transaction Submission

  • Flashbots Protect — Sends transactions directly to block builders, skipping the public mempool
  • MEV Blocker — Multi-builder protection that searches for MEV and rebates it to users
  • MEV Share — Users share a portion of their transaction's MEV in exchange for protection

Pattern 4: Slippage Protection

// Always enforce minimum output amounts
function swap(
    address tokenIn, address tokenOut,
    uint256 amountIn, uint256 minAmountOut  // User sets this
) external {
    uint256 amountOut = calculateSwap(tokenIn, tokenOut, amountIn);
    require(amountOut >= minAmountOut, "Slippage exceeded");
    // Even if frontrun, the worst case is bounded
}

Which Pattern to Use?

Use CaseRecommended Pattern
DEX swapsSlippage protection + private submission
Auctions / NFT mintsCommit-reveal or batch auction
LiquidationsBatch or Dutch auction
Token launchesBatch auction + anti-snipe
Governance votesCommit-reveal + snapshot voting
  • ✅ Default to private transaction submission for all user-facing operations
  • ✅ Implement commit-reveal for auctions and time-sensitive operations
  • ✅ Always enforce slippage tolerance parameters
  • ✅ Consider batch auctions for high-value operations

Frontrunning is a design problem, not a deployment problem. Audit your protocol's MEV exposure before you go live.

frontrunningMEVcommit-revealbatch auctionFlashbotsprivate mempool
Share

Written by

Kennedy Owiro

Founder & CTO, Vultbase

14+ years building security and QA systems at scale. Background in fintech security and Web3 smart contract testing. Built Vultbase's Intelligence Engine with 1,200+ exploit patterns from $40B+ in historical DeFi losses.

Protect your protocol before launch.

Submit your smart contracts for automated security analysis powered by 1,200+ real exploit patterns.

Start Your Audit →