MEV Vulnerabilities
Detects MEV and transaction ordering vulnerabilities in Solana programs.
MEV Vulnerabilities
Overview
The MEV vulnerabilities detector identifies patterns in Solana programs that are susceptible to Maximal Extractable Value (MEV) attacks and transaction ordering exploitation. It flags state reads followed by critical state updates without protection, AMM operations without slippage guards, price-dependent operations lacking safeguards, and sequential transaction dependencies.
For remediation guidance, see MEV Vulnerabilities Remediation.
Why This Is an Issue
Solana validators can reorder, insert, or censor transactions within a slot. Programs that read on-chain state and then perform value transfers based on that state are vulnerable to sandwich attacks: an attacker inserts a transaction before the victim to move the price, lets the victim execute at the worse price, then inserts another transaction to profit from the difference. Unlike Ethereum, Solana’s continuous block production and leader schedule make MEV extraction predictable for the current leader.
On Solana DEXes like Raydium and Orca, sandwich attacks have extracted millions in value from unprotected swaps. Programs that perform read-call-write sequences without atomic protections or slippage bounds give attackers a reliable extraction opportunity.
How to Resolve
Before (Vulnerable)
use anchor_lang::prelude::*;
// Vulnerable: reads price, performs swap, no slippage check
pub fn swap_tokens(ctx: Context<Swap>, amount_in: u64) -> Result<()> {
let price = ctx.accounts.oracle.load_price()?;
let amount_out = amount_in * price / PRECISION;
// No minimum output check -- sandwich attack possible
token::transfer(ctx.accounts.into_transfer_ctx(), amount_out)?;
Ok(())
}
After (Fixed)
use anchor_lang::prelude::*;
// Fixed: enforces minimum output and deadline
pub fn swap_tokens(
ctx: Context<Swap>,
amount_in: u64,
min_amount_out: u64,
deadline: i64,
) -> Result<()> {
let clock = Clock::get()?;
require!(clock.unix_timestamp <= deadline, ErrorCode::Expired);
let price = ctx.accounts.oracle.load_price()?;
let amount_out = amount_in * price / PRECISION;
require!(amount_out >= min_amount_out, ErrorCode::SlippageExceeded);
token::transfer(ctx.accounts.into_transfer_ctx(), amount_out)?;
Ok(())
}
Example JSON Finding
{
"detector": "mev-vulnerabilities",
"severity": "high",
"confidence": 0.7,
"message": "State read followed by value transfer without slippage protection creates MEV extraction opportunity",
"location": { "function": "swap_tokens", "block": 2, "statement": 5 }
}
Detection Methodology
- Read-call-write pattern detection: Identifies account data reads followed by CPI calls followed by state writes, flagging the race condition window.
- Transfer amount taint analysis: Tracks whether lamport or token transfer amounts derive from unvalidated on-chain state.
- Slippage guard search: Checks for comparison operations between computed output amounts and user-supplied minimum bounds.
- Transaction ordering dependency: Flags sequential operations that depend on state that could change between transaction submission and execution.
Limitations
False positives: Programs that implement off-chain slippage validation (client-side) may be flagged because the on-chain bytecode lacks the check. False negatives: Complex multi-instruction MEV strategies that span separate transactions are beyond single-function analysis scope.
Related Detectors
- Slippage Protection — detects missing slippage bounds on swaps
- Price Impact — detects missing price impact validation
- Oracle Data Freshness — detects stale oracle usage