# RToken permanently insolvent/unusable if a single collateral in the basket behaves unexpectedly

A single reverting collateral token in an RToken basket bricks unregister, refresh, issue, redeem, and staking, permanently locking all basket funds.

- Payout: Contest reward
- Severity: medium
- Program: Reserve
- Credited: 0xdeadbeef0x
- Disclosed: 2023-04-27
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-01-reserve-findings/issues/254
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-reserve%3AM-16
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:chained technique:source-review vuln:business-logic vuln:dos

**Target:** RToken collateral asset plugin / AssetRegistry / BasketHandler (Solidity)
**Root cause:** Asset unregistration and refresh flows call into the collateral token (basketHandler.quantity -> coll.refPerTok -> exchangeRateStored, and AssetRegistry.refresh -> CTokenFiatCollateral.refresh -> exchangeRateCurrent), so a collateral that reverts on any call makes unregister and refresh revert too.
**Steps:**
1. Register a CTokenFiatCollateral (e.g. cUSDP) in AssetRegistry.
2. Make the underlying cToken revert on calls (self-destruct, upgrade, freeze, blacklist).
3. Governance calls AssetRegistry.unregister(asset); it calls basketHandler.quantity(asset.erc20()) which calls coll.refPerTok() -> ICToken.exchangeRateStored() and reverts.
4. AssetRegistry.refresh() iterates assets and calls CTokenFiatCollateral.refresh() -> exchangeRateCurrent(), reverting.
5. All callers of refresh (issue, redeem, vest, poke, _manageTokens, refreshBucket, StRSR.withdraw) revert, locking funds.
**How found:** Code reading of the unregister flow: noticed basketHandler.quantity() calls coll.refPerTok() which calls into the collateral token, and that refresh() calls exchangeRateCurrent() on the token, making protocol liveness depend on external token behavior.
**Exploitation:** Not an attacker-driven exploit; a collateral token becoming non-functional (hack, upgrade, freeze, blacklist) causes protocol-wide reverts. With 1% of basket in the bad collateral, the other 99% becomes permanently unredeemable since unregister also reverts.
**Escalation:** Permanent lock: because unregister depends on the same reverting token, governance cannot remove the bad collateral, so the DoS is irreversible.
**Insight:** When auditing basket/registry contracts, trace every governance recovery path (unregister, disable, upgrade) and check whether it calls into the very external component it is meant to remove; if so, a single misbehaving dependency becomes an unrecoverable DoS.
