Every day, Solana users lose millions to MEV extraction. Sandwich attacks alone siphoned over $400M from DeFi traders in 2025. With Firedancer boosting throughput and Alpenglow on the horizon, the MEV landscape is shifting fast — and most protocol developers are not keeping up.
This guide covers the practical defense patterns every Solana DeFi developer needs in 2026: from Jito bundle integration to protocol-level architectural decisions that make sandwich attacks economically unviable.
The Solana MEV Landscape: What Changed in 2025-2026
Unlike Ethereum's proposer-builder separation (PBS) model, Solana's continuous block production and leader schedule create unique MEV dynamics. The key shifts:
Jito's Dominance. Over 95% of Solana's active stake now runs the Jito-Solana client. This means the off-chain block-building market is effectively the standard. If your protocol doesn't account for Jito bundles, you're building for a network that barely exists.
Firedancer's Throughput Jump. Higher TPS means more transactions competing for inclusion, creating new ordering games. The latency advantage for co-located searchers has narrowed, but bundle-based extraction has become more sophisticated.
Encrypted Mempools (Coming Soon). The Solana Foundation's roadmap includes encrypted transaction submission to prevent information leakage. But "coming soon" doesn't protect users today.
Anatomy of a Solana Sandwich Attack
For the uninitiated, here's how a sandwich attack works on Solana:
1. Victim submits swap: Buy Token X on Raydium
2. Attacker's front-run tx: Buy Token X (price moves up)
3. Victim's tx executes: Buys at inflated price
4. Attacker's back-run tx: Sells Token X at profit
On Solana, this happens through Jito bundles — the attacker packages all three transactions as an atomic bundle, paying the block engine a tip for guaranteed ordering.
What makes Solana sandwiches particularly nasty:
- Sub-second execution: The entire attack happens in ~400ms
- Atomic guarantee: Bundles either fully execute or revert — no partial fill risk for the attacker
- No public mempool exposure needed: With Jito's private bundle submission, the attacker's strategy stays hidden from competing searchers
Defense Pattern 1: Protocol-Level Slippage Enforcement
Most DEXs let users set slippage tolerance client-side. This is a mistake. If your protocol relies on the frontend to protect users, you've already lost.
// Bad: Trusting client-provided minimum output
pub fn swap(ctx: Context<Swap>, amount_in: u64, minimum_out: u64) -> Result<()> {
// minimum_out comes from the user — attacker can manipulate
let output = calculate_swap(amount_in, &ctx.accounts.pool)?;
require!(output >= minimum_out, ErrorCode::SlippageExceeded);
// ...
}
// Better: Protocol-enforced maximum slippage relative to oracle price
pub fn swap(ctx: Context<Swap>, amount_in: u64, user_min_out: u64) -> Result<()> {
let oracle_price = get_oracle_price(&ctx.accounts.price_feed)?;
let fair_output = calculate_fair_output(amount_in, oracle_price);
// Protocol enforces max 2% deviation from oracle price
let protocol_min = fair_output * 98 / 100;
let effective_min = std::cmp::max(user_min_out, protocol_min);
let output = calculate_swap(amount_in, &ctx.accounts.pool)?;
require!(output >= effective_min, ErrorCode::SlippageExceeded);
// ...
}
The key insight: the protocol should enforce a floor slippage tolerance even if the user's wallet sends a more permissive value. This makes sandwich attacks unprofitable for small price movements.
Practical Considerations
- Use TWAP (time-weighted average price) oracles, not spot prices — spot prices can be manipulated in the same block
- Pyth Network and Switchboard both support confidence-weighted prices on Solana; reject swaps when oracle confidence is low
- Set the protocol floor based on your pool's typical spread — too tight and legitimate trades fail, too loose and sandwiches remain profitable
Defense Pattern 2: Jito dontfront Integration
Jito's dontfront protection is the simplest defense and should be your first line. Adding the jitodontfront public key to your transaction signals the block engine to place it at index 0 in any bundle.
import { PublicKey, TransactionInstruction } from '@solana/web3.js';
const JITO_DONT_FRONT = new PublicKey(
'HFqU5x63VTqvQss8hp11i4bVqkfRtk4tY36RSSELab3e' // dontfront key
);
function addDontFrontProtection(tx: Transaction): Transaction {
// Add dontfront key as a non-signer, non-writable account
// to the first instruction
tx.instructions[0].keys.push({
pubkey: JITO_DONT_FRONT,
isSigner: false,
isWritable: false,
});
return tx;
}
Limitations you must understand:
- This is enforced by the Jito block engine, not the Solana runtime — a malicious validator not running Jito ignores it entirely
- It only prevents front-running within a bundle — it doesn't prevent cross-bundle MEV
- It's a social contract, not a cryptographic guarantee
Use it, but don't rely on it alone.
Defense Pattern 3: Commit-Reveal Swap Architecture
For high-value swaps, a commit-reveal pattern eliminates front-running entirely by hiding the swap parameters until execution:
// Phase 1: Commit (reveals nothing about swap direction or size)
pub fn commit_swap(ctx: Context<CommitSwap>, commitment: [u8; 32]) -> Result<()> {
let swap_intent = &mut ctx.accounts.swap_intent;
swap_intent.commitment = commitment;
swap_intent.commit_slot = Clock::get()?.slot;
swap_intent.user = ctx.accounts.user.key();
Ok(())
}
// Phase 2: Reveal (must happen 2+ slots after commit)
pub fn reveal_and_execute(
ctx: Context<RevealSwap>,
amount_in: u64,
minimum_out: u64,
nonce: [u8; 32],
) -> Result<()> {
let intent = &ctx.accounts.swap_intent;
let current_slot = Clock::get()?.slot;
// Enforce minimum slot gap — attacker can't front-run
// what they can't see
require!(
current_slot >= intent.commit_slot + 2,
ErrorCode::TooEarly
);
// Verify commitment
let expected = hash(&[
amount_in.to_le_bytes().as_ref(),
minimum_out.to_le_bytes().as_ref(),
nonce.as_ref(),
]);
require!(expected.to_bytes() == intent.commitment, ErrorCode::InvalidReveal);
// Execute swap with revealed parameters
execute_swap(ctx, amount_in, minimum_out)?;
Ok(())
}
Trade-offs:
- Adds latency (2 slots ≈ 800ms minimum)
- Requires two transactions instead of one
- More complex UX — wallets need to manage the two-phase flow
- Best reserved for swaps above a value threshold (e.g., >$10K)
Defense Pattern 4: Private Transaction Submission
Route user transactions through private RPC endpoints that don't broadcast to the public gossip network:
const PRIVATE_RPC_ENDPOINTS = [
'https://mainnet.block-engine.jito.wtf/api/v1/transactions',
];
async function submitPrivately(
signedTx: Transaction,
endpoints: string[] = PRIVATE_RPC_ENDPOINTS
): Promise<string> {
const serialized = signedTx.serialize();
const results = await Promise.allSettled(
endpoints.map(endpoint =>
fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'sendTransaction',
params: [bs58.encode(serialized), { encoding: 'base58' }],
}),
}).then(r => r.json())
)
);
const success = results.find(r => r.status === 'fulfilled' && !r.value.error);
if (!success) throw new Error('All private submissions failed');
return success.value.result;
}
This prevents your transaction from being visible in the gossip layer, but doesn't protect against MEV extraction by the block producer themselves.
Defense Pattern 5: Batch Auctions for AMM Pools
The most robust defense is architectural: instead of processing swaps individually, batch them.
Traditional AMM:
Swap A → executes → price moves
Swap B → executes → price moves
(Attacker inserts between A and B)
Batch Auction AMM:
Collect swaps during epoch (e.g., 4 slots)
Calculate uniform clearing price
Execute all swaps at the same price
(No ordering advantage → no sandwich profit)
This is how CoW Protocol works on Ethereum. On Solana, the challenge is that users expect sub-second execution. A practical middle ground:
- Micro-batches: Collect swaps for 2-4 slots (~800ms-1.6s), then clear
- Hybrid model: Small swaps execute instantly, large swaps (>$5K) enter the batch queue
- Frequent batch auctions (FBAs): Run auctions every N slots with a sealed-bid mechanism
This pattern fundamentally breaks sandwich economics because the attacker can't guarantee ordering within a batch.
Defense Pattern 6: CPI Guard and Transfer Hook Awareness
If your DeFi protocol interacts with Token-2022 tokens, transfer hooks add a new MEV vector. A malicious transfer hook could:
- Log transfer details to an on-chain "MEV oracle" that searchers monitor
- Introduce conditional delays that create timing advantages
- Interact with other programs in ways that leak information
pub fn safe_transfer(ctx: Context<SafeTransfer>, amount: u64) -> Result<()> {
let mint = &ctx.accounts.mint;
if let Some(hook_program) = get_transfer_hook(mint)? {
msg!("Transfer hook detected: {}", hook_program);
require!(
ALLOWED_HOOKS.contains(&hook_program),
ErrorCode::UntrustedTransferHook
);
}
transfer_checked_with_hook(ctx, amount)?;
Ok(())
}
Monitoring: Detecting MEV in Production
Defense isn't just prevention — it's detection. Set up monitoring for these signals:
- Unusual swap slippage distribution: If >5% of swaps hit the slippage limit, you're likely being targeted
- Bundle patterns: Track whether swaps consistently appear sandwiched between same-signer transactions
- Price impact anomalies: Large deviations between your pool price and oracle price at swap time
- Jito bundle analysis: Use Jito's bundle API to analyze execution ordering
interface SwapEvent {
signature: string;
slot: number;
priceImpact: number;
slippageUsed: number;
}
function detectSandwich(events: SwapEvent[]): SandwichAlert[] {
const alerts: SandwichAlert[] = [];
for (let i = 1; i < events.length - 1; i++) {
const prev = events[i - 1];
const current = events[i];
const next = events[i + 1];
if (
prev.slot === current.slot &&
current.slot === next.slot &&
current.priceImpact > 0.5 &&
Math.sign(prev.priceImpact) !== Math.sign(next.priceImpact)
) {
alerts.push({
victimTx: current.signature,
slot: current.slot,
estimatedLoss: calculateLoss(prev, current, next),
});
}
}
return alerts;
}
The Defense Stack: Putting It All Together
No single defense is sufficient. Layer them:
| Layer | Defense | Protects Against | Complexity |
|---|---|---|---|
| 1 | Jito dontfront
|
Basic front-running | Low |
| 2 | Private RPC submission | Gossip-layer snooping | Low |
| 3 | Protocol slippage floor | Wide-slippage exploitation | Medium |
| 4 | Oracle price validation | Price manipulation | Medium |
| 5 | Commit-reveal (high value) | All information leakage | High |
| 6 | Batch auctions | Ordering-based MEV | High |
| 7 | Transfer hook auditing | Token-2022 vectors | Medium |
For most protocols, layers 1-4 provide strong protection with reasonable complexity. Layers 5-6 are for protocols handling significant value where the engineering investment is justified.
What's Coming: Alpenglow and Beyond
The Alpenglow consensus rewrite (targeted mid-2026) promises sub-second finality and new transaction ordering guarantees. For MEV defense, this means:
- Reduced confirmation latency narrows the window for MEV extraction
- New scheduling algorithms may offer protocol-level ordering fairness
- Encrypted transaction submission at the protocol level would obsolete gossip-layer snooping entirely
But don't wait. The attacks are happening now. Implement layers 1-4 today, and architect for layers 5-6 as your protocol grows.
Key Takeaways
- MEV defense is not optional — it's a user safety requirement, not an optimization
- Layer your defenses — no single technique is sufficient
- Protocol-enforced slippage matters more than client-side settings
- Jito integration is table stakes — 95% of stake runs Jito, build for that reality
- Monitor continuously — detection enables response, even when prevention fails
- Token-2022 adds new vectors — audit transfer hooks in every token your protocol touches
- Architecture > patches — batch auctions fundamentally break sandwich economics
The MEV arms race on Solana is accelerating. The protocols that survive will be the ones that treat MEV protection as a core design principle, not an afterthought.
Building MEV-resistant DeFi on Solana? I'd love to hear what patterns are working (or failing) for your team. Drop a comment or reach out.
Top comments (0)