Smart contracts cannot access off-chain data directly. They rely on oracles — contracts or services that supply external data like asset prices. When a protocol trusts a manipulable price source, attackers can corrupt the data and exploit the resulting mispriced assets.
The most common target is a spot price from a decentralized exchange's liquidity pool. By executing a large swap (often funded by a flash loan), an attacker can move the price dramatically within a single block, query it while distorted, and profit from the manipulation before the price reverts.
// VULNERABLE — spot price from a single pool, easily manipulated
function collateralValue(uint tokenAmount) public view returns (uint) {
uint price = uniswapPair.token0() == WETH
? reserve1 / reserve0 // spot price, no TWAP
: reserve0 / reserve1;
return tokenAmount * price;
}
// Lending protocol uses collateralValue() to decide how much to lend
// Flash loan + swap = inflated collateral = free money
// SAFE — Chainlink price feed with staleness check
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
AggregatorV3Interface internal priceFeed;
function getPrice() public view returns (int) {
(, int price, , uint updatedAt,) = priceFeed.latestRoundData();
require(block.timestamp - updatedAt < 3600, "Stale oracle");
return price;
}