Skip to main content
Sigvex

MEV Vulnerabilities Remediation

How to fix MEV and transaction ordering vulnerabilities in Solana programs.

MEV Vulnerabilities Remediation

Overview

Related Detector: MEV Vulnerabilities

MEV attacks exploit programs that perform state-dependent value transfers without protective bounds. The primary fix is to require user-supplied slippage parameters (minimum output amounts) and execution deadlines on every value-transferring operation. Combined with atomic execution patterns, these defenses make sandwich attacks unprofitable.

Before (Vulnerable)

use anchor_lang::prelude::*;

// Vulnerable: no slippage or deadline protection
pub fn execute_swap(ctx: Context<Swap>, amount: u64) -> Result<()> {
    let price = get_current_price(&ctx.accounts.pool)?;
    let output = calculate_output(amount, price);
    transfer_tokens(&ctx, output)?;
    Ok(())
}

After (Fixed)

use anchor_lang::prelude::*;

// Fixed: user-supplied minimum output and deadline
pub fn execute_swap(
    ctx: Context<Swap>,
    amount: u64,
    min_output: u64,
    deadline: i64,
) -> Result<()> {
    let clock = Clock::get()?;
    require!(clock.unix_timestamp <= deadline, SwapError::DeadlineExceeded);

    let price = get_current_price(&ctx.accounts.pool)?;
    let output = calculate_output(amount, price);
    require!(output >= min_output, SwapError::SlippageExceeded);

    transfer_tokens(&ctx, output)?;
    Ok(())
}

Alternative Mitigations

Commit-Reveal Schemes

For operations where slippage bounds alone are insufficient, implement a two-phase commit-reveal pattern. Users commit a hashed intention in one transaction and reveal it in a later slot, preventing validators from frontrunning the actual operation.

Use a block-builder Bundles

a block-builder’s bundle mechanism allows users to submit multiple transactions atomically, reducing the window for sandwich attacks. While this is an infrastructure-level mitigation, programs should still enforce on-chain slippage bounds.

Common Mistakes

Mistake: Hardcoded Slippage Tolerance

// WRONG: hardcoded 5% slippage -- too permissive for large trades
let min_output = expected_output * 95 / 100;

Always accept the minimum output as a user-supplied parameter so traders can set appropriate bounds for their trade size.

Mistake: Missing Deadline

// WRONG: slippage check without deadline
require!(output >= min_output, SwapError::SlippageExceeded);
// Transaction could sit in mempool and execute much later at an unfavorable price

Always pair slippage checks with an expiration timestamp.

References