Vault accounts with excess cash can avoid being settled
If excess cash was transferred out from an account during account settlement, then the protocol will check the account's collateral ratio and revert if the position is unhealthy. Because it may not be possible to settle a vault account, liquidators cannot reduce account debt by purchasing vault shares because `_authenticateDeleverage()` will check to see if a vault has matured.\\nConsidering an account's health is determined by a combination of its outstanding debt, cash holdings and the total underlying value of its vault shares, transferring out excess cash may actually put an account in an unhealthy position.\\n```\\nFile: VaultAccountAction.sol\\n    function settleVaultAccount(address account, address vault) external override nonReentrant {\\n        requireValidAccount(account);\\n        require(account != vault);\\n\\n        VaultConfig memory vaultConfig = VaultConfiguration.getVaultConfigStateful(vault);\\n        VaultAccount memory vaultAccount = VaultAccountLib.getVaultAccount(account, vaultConfig);\\n        \\n        // Require that the account settled, otherwise we may leave the account in an unintended\\n        // state in this method because we allow it to skip the min borrow check in the next line.\\n        (bool didSettle, bool didTransfer) = vaultAccount.settleVaultAccount(vaultConfig);\\n        require(didSettle, "No Settle");\\n\\n        vaultAccount.accruePrimeCashFeesToDebt(vaultConfig);\\n\\n        // Skip Min Borrow Check so that accounts can always be settled\\n        vaultAccount.setVaultAccount({vaultConfig: vaultConfig, checkMinBorrow: false});\\n\\n        if (didTransfer) {\\n            // If the vault did a transfer (i.e. withdrew cash) we have to check their collateral ratio. There\\n            // is an edge condition where a vault with secondary borrows has an emergency exit. During that process\\n            // an account will be left some cash balance in both currencies. It may have excess cash in one and\\n            // insufficient cash in the other. A withdraw of the excess in one side will cause the vault account to\\n            // be insolvent if we do not run this check. If this scenario indeed does occur, the vault itself must\\n            // be upgraded in order to facilitate orderly exits for all of the accounts since they will be prevented\\n            // from settling.\\n            IVaultAccountHealth(address(this)).checkVaultAccountCollateralRatio(vault, account);\\n        }\\n    }\\n```\\n\\nIt is important to note that all vault liquidation actions require a vault to first be settled. Hence, through self-liquidation, sophisticated vault accounts can have excess cash in one currency and significant debt holdings in the vault's other currencies.\\n```\\nFile: VaultLiquidationAction.sol\\n    function _authenticateDeleverage(\\n        address account,\\n        address vault,\\n        address liquidator\\n    ) private returns (\\n        VaultConfig memory vaultConfig,\\n        VaultAccount memory vaultAccount,\\n        VaultState memory vaultState\\n    ) {\\n        // Do not allow invalid accounts to liquidate\\n        requireValidAccount(liquidator);\\n        require(liquidator != vault);\\n\\n        // Cannot liquidate self, if a vault needs to deleverage itself as a whole it has other methods \\n        // in VaultAction to do so.\\n        require(account != msg.sender);\\n        require(account != liquidator);\\n\\n        vaultConfig = VaultConfiguration.getVaultConfigStateful(vault);\\n        require(vaultConfig.getFlag(VaultConfiguration.DISABLE_DELEVERAGE) == false);\\n\\n        // Authorization rules for deleveraging\\n        if (vaultConfig.getFlag(VaultConfiguration.ONLY_VAULT_DELEVERAGE)) {\\n            require(msg.sender == vault);\\n        } else {\\n            require(msg.sender == liquidator);\\n        }\\n\\n        vaultAccount = VaultAccountLib.getVaultAccount(account, vaultConfig);\\n\\n        // Vault accounts that are not settled must be settled first by calling settleVaultAccount\\n        // before liquidation. settleVaultAccount is not permissioned so anyone may settle the account.\\n        require(block.timestamp < vaultAccount.maturity, "Must Settle");\\n\\n        if (vaultAccount.maturity == Constants.PRIME_CASH_VAULT_MATURITY) {\\n            // Returns the updated prime vault state\\n            vaultState = vaultAccount.accruePrimeCashFeesToDebtInLiquidation(vaultConfig);\\n        } else {\\n            vaultState = VaultStateLib.getVaultState(vaultConfig, vaultAccount.maturity);\\n        }\\n    }\\n```\\n\\nConsider the following example:\\nAlice has a valid borrow position in the vault which is considered risky. She has a small bit of secondary cash but most of her debt is primary currency denominated. Generally speaking her vault is healthy. Upon settlement, the small bit of excess secondary cash is transferred out and her vault is undercollateralised and eligible for liquidation. However, we are deadlocked because it is not possible to settle the vault because `checkVaultAccountCollateralRatio()` will fail, and it's not possible to purchase the excess cash and offset the debt directly via `liquidateVaultCashBalance()` or `deleverageAccount()` because `_authenticateDeleverage()` will revert if a vault has not yet been settled.
Consider adding a liquidation method which settles a vault account and allows for a liquidator to purchase vault shares, offsetting outstanding debt, before performing collateral ratio checks.
Vault accounts can create positions which will never be eligible for liquidation and the protocol may accrue bad debt.
```\\nFile: VaultAccountAction.sol\\n    function settleVaultAccount(address account, address vault) external override nonReentrant {\\n        requireValidAccount(account);\\n        require(account != vault);\\n\\n        VaultConfig memory vaultConfig = VaultConfiguration.getVaultConfigStateful(vault);\\n        VaultAccount memory vaultAccount = VaultAccountLib.getVaultAccount(account, vaultConfig);\\n        \\n        // Require that the account settled, otherwise we may leave the account in an unintended\\n        // state in this method because we allow it to skip the min borrow check in the next line.\\n        (bool didSettle, bool didTransfer) = vaultAccount.settleVaultAccount(vaultConfig);\\n        require(didSettle, "No Settle");\\n\\n        vaultAccount.accruePrimeCashFeesToDebt(vaultConfig);\\n\\n        // Skip Min Borrow Check so that accounts can always be settled\\n        vaultAccount.setVaultAccount({vaultConfig: vaultConfig, checkMinBorrow: false});\\n\\n        if (didTransfer) {\\n            // If the vault did a transfer (i.e. withdrew cash) we have to check their collateral ratio. There\\n            // is an edge condition where a vault with secondary borrows has an emergency exit. During that process\\n            // an account will be left some cash balance in both currencies. It may have excess cash in one and\\n            // insufficient cash in the other. A withdraw of the excess in one side will cause the vault account to\\n            // be insolvent if we do not run this check. If this scenario indeed does occur, the vault itself must\\n            // be upgraded in order to facilitate orderly exits for all of the accounts since they will be prevented\\n            // from settling.\\n            IVaultAccountHealth(address(this)).checkVaultAccountCollateralRatio(vault, account);\\n        }\\n    }\\n```\\n