Price Manipulation in DeFi
Price manipulation is the most common attack vector in DeFi. Every protocol that uses on‑chain price data — whether for lending, liquidations, derivatives or swaps — must understand how manipulators distort prices and how to defend against it.
1. Flash Loan & Oracle Manipulation
A flash loan gives the attacker temporary control of a large capital. They use it to skew a spot price on a DEX, then exploit a protocol that reads that spot price without validation.
// ❌ VULNERABLE — uses spot price from a single AMM
contract WeakLender {
IUniswapV2Pair public pool;
function getCollateralValue(address token) public view returns (uint256) {
(uint112 reserve0, uint112 reserve1, ) = pool.getReserves();
return token == pool.token0() ? reserve0 : reserve1;
}
function liquidate(address user) external {
uint256 coll = getCollateralValue(user);
// ...
}
}
getReserves() returns a manipulated price → liquidates a healthy position → repays flash loan.
Mitigation: Use a TWAP oracle (e.g., Uniswap V2 built‑in) instead of a single block spot price. TWAP averages the price over a period, making manipulation exponentially more expensive.
// ✅ SAFER — TWAP-based oracle
import "@uniswap/v2-periphery/contracts/libraries/UniswapV2OracleLibrary.sol";
function getCurrentTWAP(address pool, uint256 period) external view returns (uint256) {
uint256 priceCumulative = IUniswapV2Pair(pool).price0CumulativeLast();
uint256 timestamp = IUniswapV2Pair(pool).blockTimestampLast();
// use UniswapV2OracleLibrary to compute TWAP
return UniswapV2OracleLibrary.currentPrice(pool, period);
}
2. TWAP Exploitation (Time‑Weighted Average Price)
TWAP oracles are not bulletproof. If the attack spans multiple blocks or the TWAP window is too short, an attacker can still manipulate the average.
// Attack scenario: manipulate TWAP over 2 blocks
// Block 1: attacker swaps 1000 ETH, moving price from 2000 to 1500
// Block 2: attacker swaps another 1000 ETH, moving price to 1100
// TWAP(2 blocks) = (2000 + 1500 + 1100) / 3 ≈ 1533 (still far from true market)
Mitigation: Use a longer TWAP window (≥30 minutes). Combine with a price deviation check — if the current price diverges from the TWAP by more than X%, revert.
3. Sandwich Attacks (MEV)
While not a protocol vulnerability, sandwich attacks harm users. A bot observes a pending transaction, places a buy order before it and a sell order after, capturing the slippage.
// User's tx: swap 10 ETH for USDC
// Bot's front-run: buy USDC before user → price ↑
// User's tx executes at worse rate
// Bot's back-run: sell USDC → profit
Mitigation: Use slippage protection (minAmountOut). Protocols can also use batch auctions or commit‑reveal schemes.
4. Price Manipulation via Liquidity Depletion
If a pool has very low liquidity, even a small trade can cause extreme price impact. Attackers target these pools to trigger liquidations or steal funds.
// ❌ VULNERABLE — uses pool with < 1 ETH liquidity
function getPrice(address token) view returns (uint256) {
uint256 reserve = IUniswapV2Pair(pair).getReserves();
// if reserve is tiny, division yields huge price
return (reserve * 1e18) / otherReserve;
}
Mitigation: Always check minimum liquidity before trusting a price. Use a chainlink oracle as a fallback or a weighted median of multiple sources.
5. Defensive Patterns
- Use multiple oracles (Chainlink + TWAP + MakerDAO medianizer).
- Circuit breakers — pause price‑sensitive functions if price moves > X% within a block.
- L2 sequencer oracle — on L2, validate that the sequencer is alive and the price is not stale.
- minAmountOut and maxAmountIn — always enforce user‑defined limits.