# User can't redeem from RToken based on CurveStableRTokenMetapoolCollateral when any underlying collateral of paired RToken's price oracle is offline(timeout)

CurveStableRTokenMetapoolCollateral.refresh reverts via uint192 overflow in mid-price calc when paired RToken's oracle times out, blocking all RToken redemptions.

- 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-07-reserve-findings/issues/21
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-reserve%3AM-08
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:dos vuln:oracle-manipulation

**Target:** CurveStableRTokenMetapoolCollateral / CurveStableMetapoolCollateral collateral plugin
**Root cause:** When a paired RToken's underlying collateral oracle times out, RTokenAsset.price() returns high=FIX_MAX (or near it) with nonzero low; the metapool's _anyDepeggedOutsidePool computes mid=(low+high)/2 which overflows uint192 and reverts, and the FIX_MAX branch asserts low==0.
**Steps:**
1. Deploy RToken backed by CurveStableRTokenMetapoolCollateral paired with another RToken (e.g. eUSD-fraxBP).
2. Cause one underlying collateral oracle of the paired RToken to time out so RTokenAsset.price() returns low>0, high=FIX_MAX.
3. Call RToken.redeemTo/redeemCustom, which invokes assetRegistry.refresh().
4. refresh() calls _anyDepeggedOutsidePool -> tryPairedPrice -> mid=(low+high)/2 overflows uint192 and reverts (or assert(low==0) fails in the FIX_MAX branch).
5. Redemption reverts for all users.
**How found:** Read CurveStableRTokenMetapoolCollateral.tryPairedPrice and traced how RTokenAsset.price() behaves on oracle timeout (from a prior related finding), then checked the superclass refresh() overflow/assert paths and the metapool's mid-price computation.
**Exploitation:** Attacker needs only an external oracle timeout condition on any underlying collateral of the paired RToken; no capital required. Once triggered, every redeemTo/redeemCustom call reverts, freezing exits and enabling a run/depeg on the RToken.
**Insight:** When a price oracle returns a sentinel max value (FIX_MAX) with nonzero low, any downstream arithmetic like (low+high)/2 or FIX.plus can overflow uint192 and revert; audit every consumer of oracle price ranges for overflow-safe midpoint math and sentinel handling.
