Slippage Validation
Detects missing or insufficient slippage protection in DEX swap and liquidity operations, allowing MEV bots and sandwich attackers to extract value from transactions.
Slippage Validation
Overview
Remediation Guide: How to Fix Slippage Validation
The slippage validation detector identifies DEX swap and liquidity operations where the caller does not enforce a minimum output amount or transaction deadline. Without slippage protection, a swap can be sandwiched: an MEV bot front-runs the transaction to move the price, lets the victim trade at the worse rate, then back-runs to profit from the price difference. The victim receives far fewer tokens than expected, sometimes effectively zero.
Sigvex detects this pattern by identifying calls to known DEX router selectors (swapExactTokensForTokens, exactInputSingle, swapTokensForExactTokens, etc.) and checking the data-flow graph to determine whether the amountOutMin parameter is a non-zero caller-supplied value. A hardcoded zero or a value derived from an on-chain manipulable oracle is flagged as insufficient slippage protection.
Why This Is an Issue
Slippage is the difference between the expected and actual execution price of a swap. MEV bots continuously monitor the mempool for transactions with weak slippage protection and execute sandwich attacks: they submit a buy transaction before the victim (pushing the price up), allow the victim’s transaction to execute at the inflated price, then immediately sell back to restore the price — keeping the difference. The victim receives fewer tokens but the overall trade volume and gas appear normal.
The attack is especially severe in automated vault strategies (auto-compounders) that perform swaps during rebalancing without user-specified slippage parameters. A single bot can extract value from every compound cycle.
MEV sandwich attacks extracted an estimated $1.3 billion in 2023 from DEX users, with the majority targeting transactions with zero or near-zero slippage protection.
How to Resolve
Expose slippage parameters to callers and validate them against a freshly-computed price estimate. Do not use block.timestamp as a deadline — it provides no protection against delayed execution.
// Before: Vulnerable — hardcoded zero minimum output and no deadline
function swapTokens(address tokenIn, address tokenOut, uint256 amount) external {
IERC20(tokenIn).transferFrom(msg.sender, address(this), amount);
IERC20(tokenIn).approve(address(router), amount);
address[] memory path = new address[](2);
path[0] = tokenIn;
path[1] = tokenOut;
router.swapExactTokensForTokens(
amount,
0, // VULNERABLE: accepts any output, even near-zero
path,
msg.sender,
block.timestamp // VULNERABLE: no execution window limit
);
}
// After: Fixed — caller-specified minimum output and deadline
function swapTokens(
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOutMin, // Caller specifies acceptable slippage
uint256 deadline // Caller specifies execution window
) external {
require(deadline > block.timestamp, "Deadline in past");
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).approve(address(router), amountIn);
address[] memory path = new address[](2);
path[0] = tokenIn;
path[1] = tokenOut;
router.swapExactTokensForTokens(amountIn, amountOutMin, path, msg.sender, deadline);
}
Examples
Vulnerable Code
interface IUniswapV2Router {
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
}
contract VulnerableVault {
IUniswapV2Router public router;
// VULNERABLE: performs swap with zero slippage protection
function compound() external {
uint256 rewards = _claimRewards();
address[] memory path = new address[](2);
path[0] = REWARD_TOKEN;
path[1] = WANT_TOKEN;
// amountOutMin = 0: sandwich bot can extract most of the swap value
// deadline = block.timestamp: no protection against delayed execution
router.swapExactTokensForTokens(rewards, 0, path, address(this), block.timestamp);
}
}
Fixed Code
contract SafeVault {
IUniswapV2Router public router;
uint256 public constant MAX_SLIPPAGE_BPS = 100; // 1% maximum slippage
// FIXED: caller provides minimum output and deadline
function compound(uint256 minOut, uint256 deadline) external {
require(deadline > block.timestamp, "Deadline in past");
uint256 rewards = _claimRewards();
address[] memory path = new address[](2);
path[0] = REWARD_TOKEN;
path[1] = WANT_TOKEN;
// Validate caller-provided minimum against current on-chain price
uint256[] memory amounts = router.getAmountsOut(rewards, path);
uint256 expectedOut = amounts[amounts.length - 1];
uint256 minimumOut = expectedOut * (10000 - MAX_SLIPPAGE_BPS) / 10000;
require(minOut >= minimumOut, "Slippage tolerance exceeded");
router.swapExactTokensForTokens(rewards, minOut, path, address(this), deadline);
}
}
Sample Sigvex Output
{
"detector_id": "slippage-validation",
"severity": "critical",
"confidence": 0.90,
"description": "Call to swapExactTokensForTokens at offset 0x7c passes amountOutMin = 0 (constant) and deadline = TIMESTAMP. No slippage protection is enforced. Sandwich attack is possible.",
"location": {
"function": "compound()",
"offset": 124
}
}
Detection Methodology
Sigvex identifies slippage vulnerabilities through selector-matching and data-flow analysis:
- DEX router call identification: Recognizes known DEX router function selectors (Uniswap V2, V3, Curve, Balancer, and others) via Sigvex’s function selector database.
- amountOutMin analysis: Traces the data flow of the minimum output parameter. Flags the call if the value is a constant zero, a very small constant, or derived from an on-chain manipulable oracle (TWAP sources are not flagged).
- Deadline analysis: Checks the deadline parameter. Flags
block.timestamppassed directly as the deadline (provides no meaningful window protection). Validates that non-zero deadline offsets are within a reasonable range. - Protocol-level slippage: For vault contracts that embed swaps in compound or rebalance functions, checks whether the function signature exposes slippage parameters to the caller.
Confidence is High when the minimum output is a compile-time constant zero and the swap amount is derived from user funds or accumulated rewards.
Limitations
False positives:
- Protocols that implement slippage checks in a separate validation call before the swap may be flagged if Sigvex cannot resolve the inter-procedural data flow from bytecode alone.
- Flash loan callbacks where the swap is guaranteed by external atomic arbitrage constraints may produce false positives.
False negatives:
- Slippage expressed as a percentage of current price derived from a manipulable oracle (e.g.,
getReserves()) is technically present but provides no real protection — this is detected separately by theoracle-manipulationdetector.
Related Detectors
- Oracle Manipulation — detects manipulable price sources used as slippage references
- Flash Loan — detects flash loan attack vectors related to price manipulation
- Front-Running — detects general front-running and MEV exposure patterns