MEV Protection: How to Prevent Sandwich Attacks on Your DeFi Trades
MEV Protection: How to Prevent Sandwich Attacks on Your DeFi Trades
Every unprotected DEX swap is a potential victim. MEV bots extracted over $680M from Ethereum users in 2023. Here's how they work and how to defend yourself.
Anatomy of a Sandwich Attack
1. You submit: Swap 10 ETH → USDC (appears in mempool)
2. Bot sees your tx and calculates your slippage tolerance
3. Bot front-runs: Buys ETH (price goes up)
4. Your tx executes at a worse price
5. Bot back-runs: Sells ETH (takes profit)
Your loss = Bot's profit + gas fees
Detection Script
from web3 import Web3
import json
def detect_sandwich(tx_hash: str, w3: Web3) -> dict:
"""Check if a transaction was sandwiched."""
receipt = w3.eth.get_transaction_receipt(tx_hash)
block = w3.eth.get_block(
receipt['blockNumber'], full_transactions=True
)
tx_index = receipt['transactionIndex']
our_tx = block['transactions'][tx_index]
# Check for suspicious txs from same address
# immediately before and after ours
sandwiched = False
attacker = None
if tx_index > 0 and tx_index < len(block['transactions']) - 1:
tx_before = block['transactions'][tx_index - 1]
tx_after = block['transactions'][tx_index + 1]
# Same sender for before and after = likely sandwich
if tx_before['from'] == tx_after['from']:
if tx_before['from'] != our_tx['from']:
sandwiched = True
attacker = tx_before['from']
return {
'sandwiched': sandwiched,
'attacker': attacker,
'block': receipt['blockNumber'],
'tx_index': tx_index,
}
Protection Strategies
1. Use Flashbots Protect RPC
# Instead of sending to the public mempool,
# send directly to block builders via Flashbots
FLASHBOTS_RPC = "https://rpc.flashbots.net"
w3_protected = Web3(Web3.HTTPProvider(FLASHBOTS_RPC))
# Your transaction is never visible in the public mempool
# Block builders include it directly
2. Smart Slippage Calculation
def calculate_safe_slippage(
amount_in: float,
pool_reserves: float,
historical_volatility: float,
) -> float:
"""Calculate minimum safe slippage tolerance."""
# Price impact from our trade
price_impact = amount_in / pool_reserves
# Expected price movement during 1 block (~12s)
block_volatility = historical_volatility * (12 / 86400) ** 0.5
# Minimum slippage = impact + 1 block of volatility + buffer
min_slippage = price_impact + block_volatility * 2 + 0.001
# Cap at a reasonable maximum
return min(min_slippage, 0.05) # Max 5%
# Example
slippage = calculate_safe_slippage(
amount_in=10_000,
pool_reserves=5_000_000,
historical_volatility=0.60, # 60% annual vol
)
print(f"Recommended slippage: {slippage:.2%}")
3. Commit-Reveal Pattern
For large trades, submit in two phases:
import hashlib
def create_commit(order_details: dict, secret: str) -> str:
"""Phase 1: Commit hash of your order."""
message = json.dumps(order_details) + secret
return hashlib.sha256(message.encode()).hexdigest()
def reveal_order(order_details: dict, secret: str):
"""Phase 2: Reveal and execute after commit is on-chain."""
# Submit actual order with proof
pass
Protection Checklist
| Method | Effectiveness | Ease |
|---|---|---|
| Flashbots Protect RPC | High | Easy (change RPC URL) |
| Tight slippage | Medium | Easy |
| Order splitting | Medium | Moderate |
| Private mempool (MEV Blocker) | High | Easy |
| Commit-reveal | Very High | Complex |
| Use L2 (lower MEV) | High | Easy |
Protecting users from MEV is a core design principle of the ClawDUX escrow system, where USDC settlements happen through dedicated smart contracts rather than open DEX swaps.
The core logic discussed in this article has been integrated into the ClawDUX API. Access ClawDUX-core for full permissions, or browse the marketplace to discover verified trading strategies.