# Ineffective TWAV Implementation

Nibbl's TWAV averages only 4 observations (~1 min), letting an attacker pump valuation, reject a buyout, and dump shares within one minute.

- Payout: Audit contest
- Severity: medium
- Program: Nibbl
- Found by: xiaoming90
- Disclosed: 2022-08-01
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2022-06-nibbl#m-04
- Library page: http://bugbountylibrary.com/r/c4%3A2022-06-nibbl%3AM-04
- Tags: area:web3 domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** NibblVault buyout/TWAV oracle (Twav.sol)
**Root cause:** _getTwav averages only the last 4 observations in a fixed ring buffer, so it is observation-weighted over ~1 minute rather than time-weighted over a meaningful window, making the valuation cheap to manipulate.
**Steps:**
1. Attacker calls `buy()` to raise current valuation to the 120 ETH rejection price (block 100, t=0).
2. Calls `updateTWAV()` each subsequent block (101-103) so 120 ETH fills three observation slots.
3. Calls `sell()` in block 104; `_updateTWAV` writes the fourth slot, then `_rejectBuyout()` triggers `_getTwav()` returning 120 ETH.
4. Buyout is rejected, shares burned, attacker recovers funds within ~1 minute.
**How found:** Read the _getTwav/_updateTWAV code and noticed the ring buffer of 4 observations makes the 'time-weighted' average actually observation-weighted over ~1 minute, then constructed a block-by-block buy/update/sell sequence to reject a buyout.
**Exploitation:** Attacker buys to push valuation above the rejection threshold, refreshes TWAV over 4 consecutive blocks (~1 min), then sells to trigger _rejectBuyout with a manipulated TWAV, unwinding the buyout before arbitrageurs can react; front-running/high gas minimizes the window.
**Insight:** When a protocol claims a TWAP, check whether the accumulator is indexed by time or by a fixed observation count; a small ring buffer (e.g. 4 slots) collapses the window to a few blocks and is manipulable by refreshing observations each block.

