#  Oracle timeout at rebalance will result in a sell-off of all RSRs at 0 price

RSR oracle timeout returns price (0, FIX_MAX), causing RecollateralizationLib to auction all BackingManager and stRSR RSR at zero price.

- Payout: Contest reward
- Severity: medium
- Program: Reserve
- Credited: ronnyx2017
- Disclosed: 2023-11-13
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-06-reserve-findings/issues/15
- Library page: https://bugbountylibrary.com/r/c4%3A2023-06-reserve%3AM-06
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:oracle-manipulation

**Target:** RecollateralizationLibP1.nextTradePair / Asset.price() oracle fallback
**Root cause:** Asset.price() returns (0, FIX_MAX) on oracle timeout instead of reverting; nextTradePair uses this low price to size the RSR sell trade, so prepareTradeSell dumps the full rsrAvailable at ~0.
**Steps:**
1. Set up basket with two stablecoins, issue RTokens, stake RSR.
2. Trigger collateral default so basket switches and RSR becomes the deficit asset.
3. Run auctions to settle the collateral trade.
4. Call `setInvalidOracleTimestamp(rsrAsset)` to simulate RSR oracle timeout.
5. Call `facadeTest.runAuctionsForAllTraders(rToken.address)`.
6. Observe TradeStarted selling full stRSR RSR balance (stakeAmount) at ~0 price; stRSR RSR balance ends at 0.
**How found:** Code reading of Asset.price() catch branch returning (0, FIX_MAX) on oracle timeout, then tracing nextTradePair and prepareTradeSell to see the full rsrAvailable is sold at that low price; confirmed with a hardhat PoC using setInvalidOracleTimestamp.
**Exploitation:** Attacker waits for RSR oracle timeout during a rebalance where RSR is the deficit asset; the protocol starts a GnosisTrade selling all BackingManager+stRSR RSR at near-zero. A bidder (or anyone monitoring) buys the RSR cheaply in the batch auction, extracting value from stRSR holders.
**Insight:** When a price oracle wrapper returns a permissive (0, MAX) fallback instead of reverting, any downstream sizing logic that trusts the low bound will dump the entire balance; check every consumer of price() for timeout paths, especially where the asset is the protocol's own token.
