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.
Recommended Fix
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 Jito Bundles
Jito’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.