# Front-Running and MEV — How Bots Exploit Your Transactions
Every Ethereum transaction sits in the mempool before inclusion. During this window, bots scan for profitable opportunities — front-running, sandwiching, and extracting MEV (Maximal Extractable Value).
What Is Front-Running?
Front-running occurs when a bot sees your pending transaction and submits its own with higher gas to execute first.
Classic Example: DEX Trade
You submit:
uniswap.swapExactTokensForTokens(
1000 * 1e18, // 1000 USDC
950 * 1e18, // Min 950 DAI
path,
msg.sender,
deadline
);
A bot:
Sandwich Attacks
More sophisticated than simple front-running:
1. Bot sees your buy order (1000 USDC → DAI)
Bot front-runs: Buys DAI (raises price)
Your transaction executes (you pay inflated price)
Bot back-runs: Sells DAI (profits from price difference)
Code Pattern
// Victim transaction (in mempool)
function swap() external {
router.swapExactTokensForTokens(
1000e18,
950e18, // 5% slippage tolerance
path,
victim,
deadline
);
}
// Bot front-run (higher gas priority)
// Bot buys DAI, raising price
// Victim executes at worse price
// Bot back-run (sells for profit)
Real-World MEV Examples
1. Liquidation Front-Running
// DeFi protocol liquidation
function liquidate(address user) external {
require(isUndercollateralized(user), "Safe");
uint256 debt = getDebt(user);
uint256 collateral = getCollateral(user);
// Transfer collateral to liquidator
collateral.transfer(msg.sender, collateral);
// Liquidator profit = collateral - debt
}
Bots monitor for undercollateralized positions and front-run human liquidators.
2. NFT Mints
function mint() external payable {
require(msg.value == 0.08 ether, "Wrong price");
require(totalSupply < 10000, "Sold out");
_mint(msg.sender, totalSupply++);
}
Bots scan for profitable mints (hype projects) and submit hundreds of transactions with escalating gas fees.
3. Oracle Updates
function updatePrice(uint256 newPrice) external onlyOracle {
oldPrice = currentPrice;
currentPrice = newPrice;
}
If price updates are public before execution, bots can front-run trades based on the new price.
Defense Mechanisms
1. Slippage Protection
function swapWithMinOutput(
uint256 amountIn,
uint256 minAmountOut, // Tight tolerance
address[] calldata path
) external {
uint256 amountOut = router.swapExactTokensForTokens(
amountIn,
minAmountOut,
path,
msg.sender,
block.timestamp
);
require(amountOut >= minAmountOut, "Slippage");
}
2. Commit-Reveal Schemes
mapping(address => bytes32) public commitments;
function commit(bytes32 hash) external {
commitments[msg.sender] = hash;
}
function reveal(uint256 value, bytes32 salt) external {
bytes32 hash = keccak256(abi.encode(value, salt));
require(commitments[msg.sender] == hash, "Invalid");
// Execute action with value
delete commitments[msg.sender];
}
Users commit to actions before revealing details.
3. Flashbots Protect
Use private mempools:
const tx = await signer.sendTransaction({
to: contract.address,
data: contract.interface.encodeFunctionData("swap", [...]),
// Send to Flashbots RPC instead of public mempool
});
4. Time Locks
mapping(address => uint256) public lastAction;
function sensitiveAction() external {
require(
block.timestamp >= lastAction[msg.sender] + 1 hours,
"Cooldown"
);
lastAction[msg.sender] = block.timestamp;
// Execute action
}
5. Batch Auctions
Instead of continuous trading, use discrete auction periods where all orders execute at the same price.
MEV Mitigation Tools
- Flashbots Protect: Private transaction submission
- CowSwap: Batch auctions + MEV protection
- MEV Blocker: RPC that shields transactions
- 1inch Fusion: Intent-based swaps with solvers
Protocol-Level Solutions
EIP-1559 & Priority Fees
// Bots must pay higher priority fees
block.basefee // Burned, can't be gamed
+ priorityFee // Goes to validator
PBS (Proposer-Builder Separation)
Separates block proposal from construction, making MEV extraction more transparent.
Key Takeaways
MEV is inherent to blockchain transparency. Design protocols assuming adversarial front-running, not trusting transaction ordering.