Vulnerability: Secondary Currency debt is not managed by the Notional Controller
Severity: low

Description:
Some of the Notional Strategy Vaults may allow for secondary currencies to be borrowed as part of the same strategy. For example, a strategy may allow for USDC to be its primary borrow currency as well as have ETH as its secondary borrow currency.\\nIn order to enter the vault, a user would have to deposit `depositAmountExternal` of the primary borrow currency when calling `VaultAccountAction.enterVault()`. This would allow the user to borrow with leverage, as long as the `vaultConfig.checkCollateralRatio()` check on that account succeeds, which is based on the initial deposit and borrow currency amounts. This collateral ratio check is then performed throughout that user account's lifecycle in that vault, such as when they try to roll their maturity, or when liquidators try to perform collateral checks to ensure there is no bad debt.\\nHowever, in the event that the vault has a secondary borrow currency as well, that additional secondary debt is not calculated as part of the `checkCollateralRatio()` check. The only debt that is being considered is the `vaultAccount.fCash` that corresponds to the primary borrow currency debt:\\n```\\nfunction checkCollateralRatio(\\n    VaultConfig memory vaultConfig,\\n    VaultState memory vaultState,\\n    VaultAccount memory vaultAccount\\n) internal view {\\n    (int256 collateralRatio, /\\* \\*/) = calculateCollateralRatio(\\n        vaultConfig, vaultState, vaultAccount.account, vaultAccount.vaultShares, vaultAccount.fCash\\n```\\n\\n```\\nfunction calculateCollateralRatio(\\n    VaultConfig memory vaultConfig,\\n    VaultState memory vaultState,\\n    address account,\\n    uint256 vaultShares,\\n    int256 fCash\\n) internal view returns (int256 collateralRatio, int256 vaultShareValue) {\\n    vaultShareValue = vaultState.getCashValueOfShare(vaultConfig, account, vaultShares);\\n\\n    // We do not discount fCash to present value so that we do not introduce interest\\n    // rate risk in this calculation. The economic benefit of discounting will be very\\n    // minor relative to the added complexity of accounting for interest rate risk.\\n\\n    // Convert fCash to a positive amount of asset cash\\n    int256 debtOutstanding = vaultConfig.assetRate.convertFromUnderlying(fCash.neg());\\n```\\n\\nWhereas the value of strategy tokens that belong to that user account are being calculated by calling `IStrategyVault(vault).convertStrategyToUnderlying()` on the associated strategy vault:\\n```\\nfunction getCashValueOfShare(\\n    VaultState memory vaultState,\\n    VaultConfig memory vaultConfig,\\n    address account,\\n    uint256 vaultShares\\n) internal view returns (int256 assetCashValue) {\\n    if (vaultShares == 0) return 0;\\n    (uint256 assetCash, uint256 strategyTokens) = getPoolShare(vaultState, vaultShares);\\n    int256 underlyingInternalStrategyTokenValue = \\_getStrategyTokenValueUnderlyingInternal(\\n        vaultConfig.borrowCurrencyId, vaultConfig.vault, account, strategyTokens, vaultState.maturity\\n    );\\n```\\n\\n```\\nfunction \\_getStrategyTokenValueUnderlyingInternal(\\n    uint16 currencyId,\\n    address vault,\\n    address account,\\n    uint256 strategyTokens,\\n    uint256 maturity\\n) private view returns (int256) {\\n    Token memory token = TokenHandler.getUnderlyingToken(currencyId);\\n    // This will be true if the the token is "NonMintable" meaning that it does not have\\n    // an underlying token, only an asset token\\n    if (token.decimals == 0) token = TokenHandler.getAssetToken(currencyId);\\n\\n    return token.convertToInternal(\\n        IStrategyVault(vault).convertStrategyToUnderlying(account, strategyTokens, maturity)\\n    );\\n}\\n```\\n\\nFrom conversations with the Notional team, it is assumed that this call returns the strategy token value subtracted against the secondary currencies debt, as is the case in the `Balancer2TokenVault` for example. In other words, when collateral ratio checks are performed, those strategy vaults that utilize secondary currency borrows would need to calculate the value of strategy tokens already accounting for any secondary debt. However, this is a dependency for a critical piece of the Notional controller's strategy vaults collateral checks.\\nTherefore, even though the strategy vaults' code and logic would be vetted before their whitelisting into the Notional system, they would still remain an external dependency with relatively arbitrary code responsible for the liquidation infrastructure that could lead to bad debt or incorrect liquidations if the vaults give inaccurate information, and thus potential loss of funds.

Impact:

Recommended mitigation:
Specific strategy vault implementations using secondary borrows were not in scope of this audit. However, since the core Notional Vault system was, and it includes secondary borrow currency functionality, from the point of view of the larger Notional system it is recommended to include secondary debt checks within the Notional controller contract to reduce external dependency on the strategy vaults' logic.