A single external protocol can DOS rebalancing process
A failure in an external money market can DOS the entire rebalance process in Notional.\\n```\\nFile: ProportionalRebalancingStrategy.sol\\n    function calculateRebalance(\\n        IPrimeCashHoldingsOracle oracle,\\n        uint8[] calldata rebalancingTargets\\n    ) external view override onlyNotional returns (RebalancingData memory rebalancingData) {\\n        address[] memory holdings = oracle.holdings();\\n..SNIP..\\n        for (uint256 i; i < holdings.length;) {\\n            address holding = holdings[i];\\n            uint256 targetAmount = totalValue * rebalancingTargets[i] / uint256(Constants.PERCENTAGE_DECIMALS);\\n            uint256 currentAmount = values[i];\\n\\n            redeemHoldings[i] = holding;\\n            depositHoldings[i] = holding;\\n..SNIP..\\n        }\\n\\n        rebalancingData.redeemData = oracle.getRedemptionCalldataForRebalancing(redeemHoldings, redeemAmounts);\\n        rebalancingData.depositData = oracle.getDepositCalldataForRebalancing(depositHoldings, depositAmounts);\\n    }\\n```\\n\\nDuring a rebalance, the `ProportionalRebalancingStrategy` will loop through all the holdings and perform a deposit or redemption against the external market of the holdings.\\nAssume that Notional integrates with four (4) external money markets (Aave V2, Aave V3, Compound V3, Morpho). In this case, whenever a rebalance is executed, Notional will interact with all four external money markets.\\n```\\nFile: TreasuryAction.sol\\n    function _executeDeposits(Token memory underlyingToken, DepositData[] memory deposits) private {\\n..SNIP..\\n            for (uint256 j; j < depositData.targets.length; ++j) {\\n                // This will revert if the individual call reverts.\\n                GenericToken.executeLowLevelCall(\\n                    depositData.targets[j], \\n                    depositData.msgValue[j], \\n                    depositData.callData[j]\\n                );\\n            }\\n```\\n\\n```\\nFile: TokenHandler.sol\\n    function executeMoneyMarketRedemptions(\\n..SNIP..\\n            for (uint256 j; j < data.targets.length; j++) {\\n                // This will revert if the individual call reverts.\\n                GenericToken.executeLowLevelCall(data.targets[j], 0, data.callData[j]);\\n            }\\n```\\n\\nHowever, as long as one external money market reverts, the entire rebalance process will be reverted and Notional would not be able to rebalance its underlying assets.\\nThe call to the external money market can revert due to many reasons, which include the following:\\nChanges in the external protocol's interfaces (e.g. function signatures modified or functions added or removed)\\nThe external protocol is paused\\nThe external protocol has been compromised\\nThe external protocol suffers from an upgrade failure causing an error in the new contract code.
Consider implementing a more resilient rebalancing process that allows for failures in individual external money markets. For instance, Notional could catch reverts from individual money markets and continue the rebalancing process with the remaining markets.
Notional would not be able to rebalance its underlying holding if one of the external money markets causes a revert. The probability of this issue occurring increases whenever Notional integrates with a new external money market\\nThe 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: ProportionalRebalancingStrategy.sol\\n    function calculateRebalance(\\n        IPrimeCashHoldingsOracle oracle,\\n        uint8[] calldata rebalancingTargets\\n    ) external view override onlyNotional returns (RebalancingData memory rebalancingData) {\\n        address[] memory holdings = oracle.holdings();\\n..SNIP..\\n        for (uint256 i; i < holdings.length;) {\\n            address holding = holdings[i];\\n            uint256 targetAmount = totalValue * rebalancingTargets[i] / uint256(Constants.PERCENTAGE_DECIMALS);\\n            uint256 currentAmount = values[i];\\n\\n            redeemHoldings[i] = holding;\\n            depositHoldings[i] = holding;\\n..SNIP..\\n        }\\n\\n        rebalancingData.redeemData = oracle.getRedemptionCalldataForRebalancing(redeemHoldings, redeemAmounts);\\n        rebalancingData.depositData = oracle.getDepositCalldataForRebalancing(depositHoldings, depositAmounts);\\n    }\\n```\\n