# Degenerate TWAP oracle windows

Short, retroactive or derived-input TWAPs where one trade or input sets the price

_Area: DeFi oracles, liquidations and flash loans. Seen in 24 disclosed reports; latest 2026-09-09. Updated 2026-10-23._

## How it works
A TWAP is meant to average price over time so no single trade sets it. That guarantee breaks when the averaged input is not a raw price over a long enough window. Three concrete failures: the averaged input scales with trade size, so a large trade gets a better average than a small one [E1](https://bugbountylibrary.com/r/sherlock%3A2024-06-velocimeter%3AH-7.md); the cumulative is written after reserves change, so the new mid-price is multiplied by the whole elapsed window retroactively [E2](https://bugbountylibrary.com/r/c4%3A2024-03-abracadabra-money%3AH-01.md); or the accumulator is fed a derived value (a moving average, an average price) instead of the raw observed price, so the average is computed from itself [E4](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AH-1.md)[E8](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-04.md). The invariant: the valuation price must be an average of raw observed prices over a window long enough that no single transaction moves it, with the cumulative updated before reserves change.

## Where it shows up
- Cumulative/TWAP update called after reserve mutation [E2](https://bugbountylibrary.com/r/c4%3A2024-03-abracadabra-money%3AH-01.md)
- Short per-pool window on a thin or imbalanced pool while a deeper pool exists [E3](https://bugbountylibrary.com/r/dhl%3A20260909-ensofinance.md)
- Moving-average value written back into the accumulator it is computed from [E4](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AH-1.md)
- "TWAP" formula that algebraically reduces to current spot [E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-01.md)
- Averaging AMM quote outputs (amountOut) that scale with trade size instead of prices [E1](https://bugbountylibrary.com/r/sherlock%3A2024-06-velocimeter%3AH-7.md)
- Accumulator storing a derived averagePrice, with elapsed time back-derived by division [E8](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-04.md)
- TWAP falling back to last fill price on inactivity, ignoring fill size [E5](https://bugbountylibrary.com/r/sherlock%3A2023-04-hubble-exchange%3AM-6.md)
- Lookback loop using a timestamp from a different observation than the tick it evaluates [E7](https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-5.md)

## How to review
The property: the price must be an average of raw observed prices over a window long enough that no single transaction moves it, with the cumulative updated before reserves change. Check:
- Ordering of cumulative update vs reserve mutation [E2](https://bugbountylibrary.com/r/c4%3A2024-03-abracadabra-money%3AH-01.md)
- Window length and pool depth vs an alternate deeper pool for the same asset [E3](https://bugbountylibrary.com/r/dhl%3A20260909-ensofinance.md)
- Whether any derived value feeds back into the accumulator [E4](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AH-1.md)[E8](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-04.md)
- Substitute the TWAP formula algebraically; if it equals spot, it is not an average [E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-01.md)
- Whether the averaged input scales with trade size [E1](https://bugbountylibrary.com/r/sherlock%3A2024-06-velocimeter%3AH-7.md)
- Whether inactivity fallback weights a single uncapped fill [E5](https://bugbountylibrary.com/r/sherlock%3A2023-04-hubble-exchange%3AM-6.md)
- Whether lookback timestamps and ticks come from the same observation [E7](https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-5.md)

## Variants seen
- Size-dependent quote averaged as price [E1](https://bugbountylibrary.com/r/sherlock%3A2024-06-velocimeter%3AH-7.md)
- Retroactive cumulative after reserve change [E2](https://bugbountylibrary.com/r/c4%3A2024-03-abracadabra-money%3AH-01.md)
- Short-window TWAP on imbalanced pool [E3](https://bugbountylibrary.com/r/dhl%3A20260909-ensofinance.md)
- Recursive moving average [E4](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AH-1.md)
- Last-fill fallback with unweighted size [E5](https://bugbountylibrary.com/r/sherlock%3A2023-04-hubble-exchange%3AM-6.md)
- TWAP collapsing algebraically to spot [E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-01.md)
- Off-by-one lookback [E7](https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-5.md)
- Derived average accumulated instead of raw price [E8](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-04.md)

## Impact and severity
Inflated share minting and vault drains (~9x overvaluation) [E3](https://bugbountylibrary.com/r/dhl%3A20260909-ensofinance.md), exploitable price queries [E2](https://bugbountylibrary.com/r/c4%3A2024-03-abracadabra-money%3AH-01.md), masked feed failures [E4](https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AH-1.md), wrong lend/borrow pricing [E8](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-04.md), ineffective slippage checks [E6](https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-01.md), premium theft from counterparties [E5](https://bugbountylibrary.com/r/sherlock%3A2023-04-hubble-exchange%3AM-6.md), bad-price rebalances [E7](https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-5.md). Severity rises with pool thinness, short windows, and whether the price directly gates share minting or liquidation.

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2024-06-velocimeter%3AH-7.md
- E2: https://bugbountylibrary.com/r/c4%3A2024-03-abracadabra-money%3AH-01.md
- E3: https://bugbountylibrary.com/r/dhl%3A20260909-ensofinance.md
- E4: https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AH-1.md
- E5: https://bugbountylibrary.com/r/sherlock%3A2023-04-hubble-exchange%3AM-6.md
- E6: https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-01.md
- E7: https://bugbountylibrary.com/r/sherlock%3A2025-02-yieldoor%3AM-5.md
- E8: https://bugbountylibrary.com/r/c4%3A2026-01-olas%3AH-04.md
