# Custom redemption might revert if old assets were unregistered

BasketHandler.quoteCustomRedemption sized erc20sAll by assetRegistry.size(), so an unregistered asset still in an old basket caused index-out-of-bounds, blocking custom redemption.

- Payout: Contest reward
- Severity: high
- Program: Reserve
- Credited: 0xA5DF
- Disclosed: 2023-11-13
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-06-reserve-findings/issues/4
- Library page: https://bugbountylibrary.com/r/c4%3A2023-06-reserve%3AH-01
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** BasketHandler.quoteCustomRedemption / redeemCustom in Reserve protocol
**Root cause:** erc20sAll is allocated with length assetRegistry.size(), but the loop pushes every asset from the old basket including unregistered ones, exceeding the array length and reverting with index out of bounds.
**Steps:**
1. Deploy RToken with basket 0.9 USDC, 0.05 USDT, 0.05 DAI
2. Governance votes to change basket to 0.9 DAI, 0.1 USDC and unregisters USDT
3. Pause trading before execution so basket switch occurs but rebalance cannot run; backing manager still holds old-basket assets
4. User calls redeemCustom using the old basket
5. quoteCustomRedemption allocates `erc20sAll` of length assetRegistry.size() (2) then pushes 3 assets in the loop, reverting index out of bounds
**How found:** Code reading: noticed quoteCustomRedemption assumes max erc20sAll size equals assetRegistry.size(), then reasoned that unregistered assets can persist in old baskets making basket size larger than registry size.
**Insight:** When an array is pre-sized from a registry's current size but filled from historical basket state, unregistration creates a size mismatch; check every place registry size is used as a bound against persisted basket data.
