Skip to main content
Sigvex

TWAP Oracle Manipulation

Detects time-weighted average price oracle implementations vulnerable to multi-block manipulation or insufficient observation windows.

TWAP Oracle Manipulation

Overview

The TWAP oracle detector identifies contracts that use time-weighted average price oracles with insufficient observation windows, missing manipulation checks, or vulnerable cardinality settings. TWAP oracles compute an average price over a time window to resist single-block manipulation, but they remain vulnerable to multi-block attacks, especially on L2s where block times are short and sequencer control is centralized.

Why This Is an Issue

A TWAP oracle with a 10-minute window on an L2 with 2-second blocks requires manipulating only 300 blocks. Post-merge Ethereum with proposer-builder separation allows a single validator to control consecutive blocks, making short TWAP windows exploitable even on L1. The Euler Finance attack ($197M, 2023) and Mango Markets exploit ($114M, 2022) both involved oracle manipulation that TWAP windows failed to prevent.

How to Resolve

// Before: Short TWAP window on L2
function getPrice(address token) external view returns (uint256) {
    (int24 tick, ) = pool.observe([uint32(600), uint32(0)]); // 10 min window
    return _tickToPrice(tick);
}

// After: Longer window with manipulation detection
function getPrice(address token) external view returns (uint256) {
    uint32 window = 1800; // 30-minute minimum
    (int24 twapTick, ) = pool.observe([window, uint32(0)]);
    (int24 spotTick, ) = pool.observe([uint32(0), uint32(0)]);

    // Deviation check: spot vs TWAP
    int24 deviation = spotTick > twapTick ? spotTick - twapTick : twapTick - spotTick;
    require(deviation < MAX_DEVIATION, "Price anomaly");

    return _tickToPrice(twapTick);
}

Examples

Sample Sigvex Output

{
  "detector_id": "twap-oracle",
  "severity": "high",
  "confidence": 0.72,
  "description": "TWAP observation window at offset 0x94 is 600 seconds (10 minutes). On L2 with 2-second blocks, this requires manipulating only 300 blocks. Minimum recommended window is 1800 seconds.",
  "location": { "function": "getPrice(address)", "offset": 148 }
}

Detection Methodology

  1. Oracle call detection: Identifies a concentrated-liquidity AMM observe(), a stable-swap AMM price_oracle(), and custom TWAP implementations.
  2. Window analysis: Extracts the observation window duration from the call parameters.
  3. Deviation check scanning: Verifies whether spot vs. TWAP deviation checks exist.
  4. Cardinality validation: For a concentrated-liquidity AMM, checks whether increaseObservationCardinalityNext has been called with sufficient capacity.

Limitations

  • Cannot determine the specific L2 deployment context to calibrate window recommendations.
  • Custom oracle aggregators that combine TWAP with other sources may be partially analyzed.
  • Off-chain TWAP computation (indexed from events) is not detected.

References