--- name: defi-slippage-audit description: > Audit DeFi smart contracts for slippage protection vulnerabilities. Use when reviewing swap, liquidity, or aggregator contracts. Finds missing slippage params, hardcoded tolerances, sandwich attack vectors, price manipulation via TWAP manipulation, and deadline bypass patterns. Returns findings with Solidity line citations and PoC transaction traces. --- # DeFi Slippage Protection Audit ## Target scope Swap routers, AMM pools, yield aggregators, DEX integrations, vault harvest functions. ## Phase 1: Parameter Audit ### Missing slippage parameters ```solidity // 🚨 No minAmountOut β€” full sandwich attack surface function swap(address tokenIn, address tokenOut, uint256 amountIn) external { uint256 out = router.swap(tokenIn, tokenOut, amountIn, 0); // ← 0 = no protection } // βœ… User-controlled minimum function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut) external { uint256 out = router.swap(tokenIn, tokenOut, amountIn, minAmountOut); require(out >= minAmountOut, "slippage"); } ``` **Check every swap call for:** - `amountOutMin` / `minAmountOut` / `minReceived` parameter present AND enforced - If parameter is hardcoded (`0`, `1`, constant) β†’ High severity - If parameter is user-supplied but not validated β†’ Medium severity ### Hardcoded tolerances ```solidity // 🚨 1% hardcoded β€” profitable sandwich on large trades uint256 minOut = (amountIn * 99) / 100; // 🚨 Zero slippage β€” reverts under normal market movement uint256 minOut = amountIn; ``` ## Phase 2: Price Oracle Validation ### Single-block TWAP manipulation ```solidity // 🚨 Single-block observation window (uint256 price,) = oracle.consult(token, 1); // 1-second TWAP = flashloan-manipulable // βœ… Minimum 30-minute TWAP for mainnet (uint256 price,) = oracle.consult(token, 1800); ``` ### Missing staleness check ```solidity // 🚨 Stale Chainlink price accepted (, int256 price,,,) = feed.latestRoundData(); // no check on updatedAt // βœ… Check freshness (, int256 price,, uint256 updatedAt,) = feed.latestRoundData(); require(block.timestamp - updatedAt <= MAX_STALENESS, "stale price"); ``` ## Phase 3: Deadline Checks ```solidity // 🚨 No deadline β€” MEV can hold the transaction indefinitely router.swapExactTokensForTokens(amountIn, minOut, path, to); // 🚨 Deadline passed to router but set to max β€” useless router.swapExactTokensForTokens(amountIn, minOut, path, to, type(uint256).max); // βœ… Caller-controlled deadline function swap(..., uint256 deadline) external { require(deadline >= block.timestamp, "expired"); router.swapExactTokensForTokens(amountIn, minOut, path, to, deadline); } ``` ## Phase 4: Harvest / Autocompound Functions ```solidity // 🚨 Harvest with no slippage on reward swap β€” MEV bot sandwich function harvest() external { uint256 rewards = claimRewards(); router.swapExactTokensForTokens(rewards, 0, rewardToAsset, address(this), block.timestamp); } // βœ… Off-chain slippage oracle or permissioned harvest function harvest(uint256 minReceived) external onlyKeeper { uint256 rewards = claimRewards(); router.swapExactTokensForTokens(rewards, minReceived, rewardToAsset, address(this), block.timestamp + 60); } ``` ## Output Format ``` ## [S-01] Missing slippage parameter in swap() β€” High **Contract:** SwapRouter.sol:142 **Impact:** Attacker sandwiches every trade, extracting up to X% per swap **PoC:** 1. Attacker front-runs: swap WETHβ†’USDC pushing price up 2. Victim swap executes at inflated price (minAmountOut=0 β†’ no revert) 3. Attacker back-runs: swap USDCβ†’WETH, profiting the spread **Fix:** Add `uint256 minAmountOut` parameter, enforce with `require(received >= minAmountOut)` ```