Rebalance stops working when more holdings are added
Notional would not be able to rebalance its underlying holding when more holdings are added.\\n```\\nFile: TreasuryAction.sol\\n    function _executeRebalance(uint16 currencyId) private {\\n        IPrimeCashHoldingsOracle oracle = PrimeCashExchangeRate.getPrimeCashHoldingsOracle(currencyId);\\n        uint8[] memory rebalancingTargets = _getRebalancingTargets(currencyId, oracle.holdings());\\n        (RebalancingData memory data) = REBALANCING_STRATEGY.calculateRebalance(oracle, rebalancingTargets);\\n\\n        (/* */, uint256 totalUnderlyingValueBefore) = oracle.getTotalUnderlyingValueStateful();\\n\\n        // Process redemptions first\\n        Token memory underlyingToken = TokenHandler.getUnderlyingToken(currencyId);\\n        TokenHandler.executeMoneyMarketRedemptions(underlyingToken, data.redeemData);\\n\\n        // Process deposits\\n        _executeDeposits(underlyingToken, data.depositData);\\n\\n        (/* */, uint256 totalUnderlyingValueAfter) = oracle.getTotalUnderlyingValueStateful();\\n\\n        int256 underlyingDelta = totalUnderlyingValueBefore.toInt().sub(totalUnderlyingValueAfter.toInt());\\n        require(underlyingDelta.abs() < Constants.REBALANCING_UNDERLYING_DELTA);\\n    }\\n```\\n\\nIf the underlying delta is equal to or larger than the acceptable delta, the rebalancing process will fail and revert as per Line 301 above.\\n`Constants.REBALANCING_UNDERLYING_DELTA` is currently hardcoded to $0.0001$. There is only 1 holding (cToken) in the current code base, so $0.0001$ might be the optimal acceptable delta.\\nLet $c$ be the underlying delta for cToken holding. Then, $0 <= c < 0.0001$.\\nHowever, as more external markets are added to Notional, the number of holdings will increase, and the rounding errors could accumulate. Let $a$ and $m$ be the underlying delta for aToken and morpho token respectively. Then $0 <= (c + a + m) < 0.0001$.\\nThe accumulated rounding error or underlying delta $(c + a + m)$ could be equal to or larger than $0.0001$ and cause the `_executeRebalance` function always to revert. As a result, Notional would not be able to rebalance its underlying holding.
If the acceptable underlying delta for one holding (cToken) is $\\approx0.0001$, the acceptable underlying delta for three holdings should be $\\approx0.0003$ to factor in the accumulated rounding error or underlying delta.\\nInstead of hardcoding the `REBALANCING_UNDERLYING_DELTA`, consider allowing the governance to adjust this acceptable underlying delta to accommodate more holdings in the future and to adapt to potential changes in market conditions.
Notional would not be able to rebalance its underlying holding. The key feature of Notional V3 is to allow its Treasury Manager to rebalance underlying holdings into various other money market protocols.\\nThis makes Notional more resilient to issues in external protocols and future-proofs the protocol. If rebalancing does not work, Notional will be unable to move its fund out of a vulnerable external market, potentially draining protocol funds if this is not mitigated.\\nAnother purpose of rebalancing is to allow Notional to allocate Notional V3's capital to new opportunities or protocols that provide a good return. If rebalancing does not work, the protocol and its users will lose out on the gain from the investment.\\nOn the other hand, if an external monkey market that Notional invested in is consistently underperforming or yielding negative returns, Notional will perform a rebalance to reallocate its funds to a better market. However, if rebalancing does not work, they will be stuck with a suboptimal asset allocation, and the protocol and its users will incur losses.
```\\nFile: TreasuryAction.sol\\n    function _executeRebalance(uint16 currencyId) private {\\n        IPrimeCashHoldingsOracle oracle = PrimeCashExchangeRate.getPrimeCashHoldingsOracle(currencyId);\\n        uint8[] memory rebalancingTargets = _getRebalancingTargets(currencyId, oracle.holdings());\\n        (RebalancingData memory data) = REBALANCING_STRATEGY.calculateRebalance(oracle, rebalancingTargets);\\n\\n        (/* */, uint256 totalUnderlyingValueBefore) = oracle.getTotalUnderlyingValueStateful();\\n\\n        // Process redemptions first\\n        Token memory underlyingToken = TokenHandler.getUnderlyingToken(currencyId);\\n        TokenHandler.executeMoneyMarketRedemptions(underlyingToken, data.redeemData);\\n\\n        // Process deposits\\n        _executeDeposits(underlyingToken, data.depositData);\\n\\n        (/* */, uint256 totalUnderlyingValueAfter) = oracle.getTotalUnderlyingValueStateful();\\n\\n        int256 underlyingDelta = totalUnderlyingValueBefore.toInt().sub(totalUnderlyingValueAfter.toInt());\\n        require(underlyingDelta.abs() < Constants.REBALANCING_UNDERLYING_DELTA);\\n    }\\n```\\n