Platform Strategies Docs Blog About Launch App

MEV Protection

Learn how to protect your transactions from MEV attacks, frontrunning, and sandwich attacks. Discover tools and techniques to secure your DeFi interactions.

Private Pools

Private pools (also known as dark pools or private mempool) route transactions directly to block producers without entering the public mempool, preventing MEV searchers from seeing and manipulating your trades.

How Private Pools Work

Private Transmission

Transactions sent directly to validators without public mempool exposure

Confidential Execution

Trade details remain private until block inclusion

MEV Protection

Prevents frontrunning, sandwich attacks, and other MEV exploitation

Using Flashbots Private Transaction
// Send private transaction via Flashbots
const { FlashbotsBundleProvider } = require('@flashbots/ethers-provider-bundle');

async function sendPrivateTransaction(tx) {
    const flashbotsProvider = await FlashbotsBundleProvider.create(
        provider, // ethers provider
        wallet, // signer
        'https://relay.flashbots.net' // flashbots relay
    );

    // Prepare private transaction
    const privateTx = {
        to: tx.to,
        data: tx.data,
        gasLimit: tx.gasLimit,
        gasPrice: tx.gasPrice,
        nonce: tx.nonce,
        value: tx.value
    };

    // Send via Flashbots (private mempool)
    const signedTx = await wallet.signTransaction(privateTx);
    
    const flashbotsTransaction = {
        signedTransaction: signedTx
    };

    const response = await flashbotsProvider.sendPrivateTransaction(
        flashbotsTransaction,
        3600 // 1 hour timeout
    );

    return response;
}

// Usage example
const privateTx = await sendPrivateTransaction({
    to: UNISWAP_ROUTER,
    data: swapTxData,
    gasLimit: 300000,
    gasPrice: 20000000000, // 20 gwei
    nonce: await wallet.getTransactionCount()
});

Speed Trade-off

May result in slower inclusion times compared to public mempool

Gas Costs

Sometimes requires higher gas prices for reliable inclusion

Limited Availability

Not all private services cover all types of transactions

Commit-Reveal Scheme

Commit-reveal schemes prevent MEV by revealing transaction details only after they have been included in a block, eliminating the opportunity for frontrunning.

Implementation Pattern

1

Commit Phase

Submit hash of intended transaction with deposit to prove commitment

2

Wait Period

Wait for block inclusion and minimum delay period

3

Reveal Phase

Reveal original transaction details to execute trade

4

Execution

Contract validates reveal and executes trade atomically

Commit-Reveal Smart Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract CommitRevealSwap {
    struct Commitment {
        address trader;
        uint256 amount;
        uint256 deadline;
        bool revealed;
    }
    
    mapping(bytes32 => Commitment) public commitments;
    mapping(address => uint256) public deposits;
    
    uint256 public constant REVEAL_DELAY = 2; // 2 blocks
    uint256 public constant COMMITMENT_DURATION = 100; // 100 blocks
    
    event Committed(bytes32 indexed commitmentHash, address indexed trader);
    event Revealed(bytes32 indexed commitmentHash, uint256 amount);
    event Executed(bytes32 indexed commitmentHash, address indexed trader);
    
    // Commit phase: hash transaction details
    function commitTransaction(
        bytes32 commitmentHash
    ) external payable {
        require(commitments[commitmentHash].trader == address(0), "Already committed");
        
        commitments[commitmentHash] = Commitment({
            trader: msg.sender,
            amount: msg.value,
            deadline: block.number + COMMITMENT_DURATION,
            revealed: false
        });
        
        emit Committed(commitmentHash, msg.sender);
    }
    
    // Reveal phase: submit original transaction data
    function revealTransaction(
        uint256 amount,
        uint256 maxSlippage,
        uint256 deadline
    ) external {
        bytes32 commitmentHash = keccak256(abi.encodePacked(
            msg.sender,
            amount,
            maxSlippage,
            deadline
        ));
        
        Commitment storage commitment = commitments[commitmentHash];
        require(commitment.trader == msg.sender, "Invalid commitment");
        require(!commitment.revealed, "Already revealed");
        require(block.number >= commitment.deadline - REVEAL_DELAY, "Too early");
        
        commitment.revealed = true;
        
        emit Revealed(commitmentHash, amount);
    }
    
    // Execute trade after reveal delay
    function executeTrade(
        bytes32 commitmentHash,
        address swapRouter,
        bytes calldata swapData
    ) external {
        Commitment storage commitment = commitments[commitmentHash];
        require(commitment.revealed, "Not revealed");
        require(block.number >= commitment.deadline - REVEAL_DELAY, "Reveal delay not met");
        
        // Execute swap
        (bool success,) = swapRouter.call(swapData);
        require(success, "Swap failed");
        
        // Refund any excess
        uint256 balance = address(this).balance;
        if (balance > 0) {
            payable(commitment.trader).transfer(balance);
        }
        
        emit Executed(commitmentHash, commitment.trader);
    }
}
Trade-off Analysis: While highly effective against MEV, commit-reveal schemes introduce delay and complexity. Best suited for larger trades where protection value exceeds time cost.

Time Delays

Time delays prevent MEV by ensuring transactions cannot be included in the immediate next block, giving time for market participants to react and preventing frontrunning.

Delay Strategies

Minimum Block Delay

Transactions can only execute after N blocks have passed since submission

Time-locked Execution

Trades can only be executed during specific time windows

Random Delays

Introduce randomness to prevent predictable timing attacks

Time-Delayed DEX
contract TimeDelayedDEX {
        struct DelayedSwap {
            address trader;
            address tokenIn;
            address tokenOut;
            uint256 amountIn;
            uint256 minAmountOut;
            uint256 deadline;
            bool executed;
        }
        
        uint256 public constant MIN_DELAY_BLOCKS = 3;
        mapping(bytes32 => DelayedSwap) public delayedSwaps;
        
        event SwapRequested(
            bytes32 indexed swapId,
            address indexed trader,
            uint256 executionBlock
        );
        
        function requestSwap(
            address tokenIn,
            address tokenOut,
            uint256 amountIn,
            uint256 minAmountOut
        ) external returns (bytes32 swapId) {
            swapId = keccak256(abi.encodePacked(
                msg.sender,
                tokenIn,
                tokenOut,
                amountIn,
                block.timestamp,
                block.number
            ));
            
            uint256 executionBlock = block.number + MIN_DELAY_BLOCKS;
            uint256 deadline = executionBlock + 100; // 100 block window
            
            delayedSwaps[swapId] = DelayedSwap({
                trader: msg.sender,
                tokenIn: tokenIn,
                tokenOut: tokenOut,
                amountIn: amountIn,
                minAmountOut: minAmountOut,
                deadline: deadline,
                executed: false
            });
            
            emit SwapRequested(swapId, msg.sender, executionBlock);
        }
        
        function executeSwap(bytes32 swapId) external {
            DelayedSwap storage swap = delayedSwaps[swapId];
            require(swap.trader != address(0), "Invalid swap");
            require(!swap.executed, "Already executed");
            require(block.number >= swap.deadline - 100, "Too early");
            require(block.number <= swap.deadline, "Expired");
            
            swap.executed = true;
            
            // Transfer tokens from trader
            IERC20(swap.tokenIn).transferFrom(
                swap.trader,
                address(this),
                swap.amountIn
            );
            
            // Execute swap
            (uint256 amountOut) = executeInternalSwap(
                swap.tokenIn,
                swap.tokenOut,
                swap.amountIn
            );
            
            require(amountOut >= swap.minAmountOut, "Slippage too high");
            
            // Transfer output to trader
            IERC20(swap.tokenOut).transfer(swap.trader, amountOut);
        }
    }

Slippage Protection

While not preventing MEV directly, tight slippage limits can minimize the impact of sandwich attacks and price manipulation by limiting how much the price can move against you.

Slippage Strategies

Fixed Percentage

Set maximum allowed slippage as percentage of trade value

Dynamic Slipping

Adjust slippage limits based on market conditions and volatility

Price Impact Analysis

Calculate expected price impact before executing trades

Dynamic Slippage Calculator
class SlippageProtection {
    constructor(priceOracle, volatilityCalculator) {
        this.priceOracle = priceOracle;
        this.volatilityCalculator = volatilityCalculator;
    }

    async calculateOptimalSlippage(token, tradeSize) {
        // Get current volatility
        const volatility = await this.volatilityCalculator.get24hVolatility(token);
        
        // Get liquidity depth
        const liquidity = await this.getLiquidityDepth(token);
        
        // Calculate price impact
        const priceImpact = await this.calculatePriceImpact(token, tradeSize);
        
        // Determine safe slippage limits
        let maxSlippage;
        
        if (volatility > 0.1) { // High volatility
            maxSlippage = 0.01; // 1%
        } else if (volatility > 0.05) { // Medium volatility
            maxSlippage = 0.005; // 0.5%
        } else { // Low volatility
            maxSlippage = 0.002; // 0.2%
        }
        
        // Adjust for liquidity
        if (liquidity < tradeSize * 2) {
            maxSlippage *= 0.5; // Halve slippage for low liquidity
        }
        
        // Adjust for price impact
        if (priceImpact > 0.02) { // 2% price impact
            maxSlippage *= 0.3; // Very tight slippage
        }
        
        return Math.max(0.001, Math.min(0.02, maxSlippage)); // 0.1% to 2% range
    }

    async executeProtectedTrade(trade, maxSlippage) {
        const slippage = await this.calculateOptimalSlippage(
            trade.token, 
            trade.amount
        );
        
        // Use the more conservative slippage
        const finalSlippage = Math.min(maxSlippage, slippage);
        
        const tx = await this.prepareTransaction({
            ...trade,
            slippageTolerance: finalSlippage
        });
        
        return this.sendPrivateTransaction(tx);
    }
}

Batch Auctions

Batch auctions collect all transactions for a trading pair over a time period and execute them at the same price, eliminating opportunities for frontrunning and MEV extraction.

How Batch Auctions Work

1

Order Collection

Collect all buy and sell orders during batch window

2

Order Matching

Match orders using single clearing price mechanism

3

Price Setting

Calculate fair price that maximizes trade volume

4

Atomic Settlement

Execute all matched trades at the same time

Implementation Note: While conceptually sound, batch auctions are complex to implement and require significant changes to existing DEX infrastructure.

Flashbots

Flashbots is a decentralized, open-source infrastructure for private transaction relay that prevents MEV extraction while keeping your transaction details confidential.

Validator Network

Network of validators who commit to keep transactions private

Bundle Support

Support for transaction bundles with guaranteed execution order

Open Source

Fully open source and auditable code for transparency

Eden Network

Eden Network provides a tiered private mempool service with different levels of MEV protection and priority for various user types.

Service Tiers

Eden Members

Basic MEV protection with reduced priority in the private pool

Eden Executors

Enhanced protection with higher priority and custom gas strategies

EDEN Delegates

Premium tier with highest protection and priority execution

ARPA (Anti-Recovery PRotection Algorithm)

ARPA is a privacy-preserving random number generation service that enables fair transaction ordering without revealing transaction details.

Use Case: ARPA is particularly useful for applications requiring fair randomness in transaction ordering, such as lotteries, NFT mints, and fair launch mechanisms.

MEV Inspect

MEV Inspect is an analytics platform that provides real-time monitoring and analysis of MEV activity across the Ethereum network, helping users understand and avoid MEV-related risks.

Monitoring Capabilities

Real-time Analytics

Track MEV activity patterns and identify high-risk periods

Risk Assessment

Assess MEV risk levels for different transaction types

Protection Guidance

Get recommendations for optimal protection strategies