TWAP (Time-Weighted Average Price)
A price calculation method that averages asset prices over a time period to resist short-term manipulation.
Time-Weighted Average Price (TWAP) is a pricing mechanism that calculates the average price of an asset over a specified time period, providing manipulation-resistant price data for DeFi protocols. Unlike spot prices that reflect instantaneous market conditions, TWAP smooths out short-term volatility and makes flash loan attacks economically impractical. TWAP oracles are commonly built on top of DEX liquidity pools, most notably Uniswap, and serve as on-chain price references for lending protocols, derivatives, and other DeFi applications.
Why TWAP Matters
Spot prices can be manipulated within a single transaction:
1Block N:21. Attacker takes flash loan (1M USDC)32. Swaps USDC → ETH on Uniswap (moves price up 20%)43. Uses inflated ETH price in vulnerable protocol54. Profits from price difference65. Swaps back, repays flash loan
TWAP defeats this by averaging prices over time—manipulating a 30-minute TWAP requires holding the manipulated price for 30 minutes, which is economically prohibitive.
How TWAP Works
TWAP accumulates price observations over time:
1TWAP = (Price₁ × Time₁ + Price₂ × Time₂ + ... + Priceₙ × Timeₙ) / Total Time
In Uniswap V2/V3, the contract tracks cumulative price-time values:
1// Uniswap V2 accumulator (simplified)2price0CumulativeLast += price0 * timeElapsed;3price1CumulativeLast += price1 * timeElapsed;45// To get TWAP between two observations:6twap = (priceCumulativeEnd - priceCumulativeStart) / (timeEnd - timeStart);
Uniswap V3 TWAP
Uniswap V3 stores observations in a circular buffer:
1import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";2import "@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol";34function getTWAP(5 address pool,6 uint32 period7) external view returns (uint256 price) {8 (int24 arithmeticMeanTick,) = OracleLibrary.consult(pool, period);910 price = OracleLibrary.getQuoteAtTick(11 arithmeticMeanTick,12 1e18, // Base amount13 token0, // Base token14 token1 // Quote token15 );16}
TWAP Period Selection
| Period | Manipulation Resistance | Responsiveness |
|---|---|---|
| 1 minute | Low | High |
| 10 minutes | Medium | Medium |
| 30 minutes | High | Low |
| 1 hour+ | Very High | Very Low |
Trade-off: Longer periods are more secure but respond slower to legitimate price movements.
TWAP vs Chainlink
| Aspect | TWAP | Chainlink |
|---|---|---|
| Data source | On-chain DEX | Off-chain APIs |
| Decentralization | Fully on-chain | Network of nodes |
| Manipulation cost | Time-based | Economic (stake) |
| Freshness | Configurable | Heartbeat-based |
| Coverage | DEX-listed pairs only | Curated feeds |
| Gas cost | Lower | Higher |
Many protocols use both: Chainlink as primary, TWAP as fallback or sanity check.
Security Considerations
Low Liquidity Pools
TWAP from low-liquidity pools is easier to manipulate:
1// Check pool has sufficient liquidity2require(pool.liquidity() > MIN_LIQUIDITY, "Insufficient liquidity");
Stale Observations
Pools with low trading activity may have outdated observations:
1// Verify observation is recent2(,, uint16 observationIndex, uint16 observationCardinality,,,) = pool.slot0();3(uint32 observationTimestamp,,,) = pool.observations(observationIndex);4require(block.timestamp - observationTimestamp < MAX_STALENESS, "Stale TWAP");
Price Deviation Attacks
Gradual price manipulation over the TWAP window:
1// Compare TWAP to spot price2uint256 spotPrice = getSpotPrice();3uint256 twapPrice = getTWAP(30 minutes);4uint256 deviation = calculateDeviation(spotPrice, twapPrice);5require(deviation < MAX_DEVIATION, "Price deviation too high");
Implementation Patterns
Dual Oracle System
1function getPrice() external view returns (uint256) {2 uint256 chainlinkPrice = getChainlinkPrice();3 uint256 twapPrice = getTWAP();45 // Require prices within 5% of each other6 uint256 deviation = diff(chainlinkPrice, twapPrice) * 10000 / chainlinkPrice;7 require(deviation < 500, "Oracle deviation");89 // Return average or prefer one source10 return (chainlinkPrice + twapPrice) / 2;11}
Circuit Breaker
1uint256 public lastPrice;23function getSecurePrice() external returns (uint256 price) {4 price = getTWAP();56 if (lastPrice > 0) {7 uint256 change = diff(price, lastPrice) * 10000 / lastPrice;8 require(change < MAX_PRICE_CHANGE, "Circuit breaker triggered");9 }1011 lastPrice = price;12}
Audit Checklist
When auditing TWAP implementations:
- Sufficient observation period for the use case
- Pool liquidity requirements enforced
- Staleness checks on observations
- Deviation checks against other price sources
- Proper decimal handling
- Edge cases (pool just created, no observations)
TWAP oracles provide a trust-minimized, manipulation-resistant price source for DeFi protocols, but require careful implementation to avoid edge cases and ensure sufficient security for the specific use case.
Articles Using This Term
Learn more about TWAP (Time-Weighted Average Price) in these articles:
Related Terms
Oracle
A service that provides external data (prices, events, random numbers) to smart contracts that cannot access off-chain information directly.
Price Manipulation
Attacks that artificially move asset prices to exploit protocols relying on those prices for critical operations.
Flash Loan
Uncollateralized loan borrowed and repaid within a single transaction, often used for arbitrage or attacks.
Automated Market Maker (AMM)
A decentralized exchange protocol that uses mathematical formulas to price assets instead of order books.
Need expert guidance on TWAP (Time-Weighted Average Price)?
Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.
Get a Quote

