early user can call issue() and then melt() to increase basketsNeeded to supply ratio to its maximum value and then melt() won't work and contract contract features like issue() won't work
Audit: 2023-01-reserve-findings
Severity: MEDIUM

# Lines of code

https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/RToken.sol#L563-L573
https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/RToken.sol#L801-L814
https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/RToken.sol#L219
https://github.com/reserve-protocol/protocol/blob/df7ecadc2bae74244ace5e8b39e94bc992903158/contracts/p1/Furnace.sol#L70-L84


# Vulnerability details

## Impact
Function `melt()` melt a quantity of RToken from the caller's account, increasing the basket rate. basket rate should be between `1e9` and `1e27` and function `requireValidBUExchangeRate()` checks that if it's not in interval the the code would revert. the call to `requireValidBUExchangeRate()` happens in the function `mint()`, `melt()` and `setBasketsNeeded()` which are used in `issue()` and `handoutExcessAssets()` and `compromiseBasketsNeeded()` which are used in multiple functionality of the systems. early malicious user can call `issue(1e18)` and `melt(1e18 - 1)` and then set the ratio between baskets needed and total supply to `1e27` and then any new action that increase the ratio would fail. because during the `issue()` code calls `melt()` so the issue() would fail for sure and other functionalities can increase the ratio because of the ratio too because of the rounding error which result in revert. so by exploiting this attacker can make RToken to be in broken state and most of the functionalities of the system would stop working.

## Proof of Concept
This is `melt()` code:
```
    function melt(uint256 amtRToken) external notPausedOrFrozen {
        _burn(_msgSender(), amtRToken);
        emit Melted(amtRToken);
        requireValidBUExchangeRate();
    }
```
As you can see it allows anyone to burn their RToken balance. This is `requireValidBUExchangeRate()` code:
```
    function requireValidBUExchangeRate() private view {
        uint256 supply = totalSupply();
        if (supply == 0) return;

        // Note: These are D18s, even though they are uint256s. This is because
        // we cannot assume we stay inside our valid range here, as that is what
        // we are checking in the first place
        uint256 low = (FIX_ONE_256 * basketsNeeded) / supply; // D18{BU/rTok}
        uint256 high = (FIX_ONE_256 * basketsNeeded + (supply - 1)) / supply; // D18{BU/rTok}

        // 1e9 = FIX_ONE / 1e9; 1e27 = FIX_ONE * 1e9
        require(uint192(low) >= 1e9 && uint192(high) <= 1e27, "BU rate out of range");
    }
```
As you can see it checks and makes sure that  the BU to RToken exchange rate to be in [1e-9, 1e9]. so Attacker can perform this steps:
1. add `1e18` RToken as first issuer by calling `issue()`
2. call `melt()` and burn `1e18 - 1` of his RTokens.
3. not `basketsNeeded` would be `1e18` and `totalSupply()` of RTokens would be `1` and the BU to RToken exchange rate would be its maximum value `