function redeem(uint128 vaultId, uint128 withdrawalRequestId, uint256 minAssets) external {
Vault.Data storage vault = Vault.loadLive(vaultId);
WithdrawalRequest.Data storage withdrawalRequest =
WithdrawalRequest.loadExisting(vaultId, msg.sender, withdrawalRequestId);
if (withdrawalRequest.fulfilled) revert Errors.WithdrawalRequestAlreadyFulfilled();
if (withdrawalRequest.timestamp + vault.withdrawalDelay > block.timestamp) {
revert Errors.WithdrawDelayNotPassed();
}
uint256[] memory vaultsIds = new uint256[](1);
vaultsIds[0] = uint256(vaultId);
Vault.recalculateVaultsCreditCapacity(vaultsIds);
RedeemContext memory ctx;
ctx.shares = withdrawalRequest.shares;
ctx.expectedAssetsX18 = getIndexTokenSwapRate(vaultId, ctx.shares, false);
MarketMakingEngineConfiguration.Data storage marketMakingEngineConfiguration =
MarketMakingEngineConfiguration.load();
ctx.redeemFee = vault.redeemFee;
ctx.expectedAssetsMinusRedeemFeeX18 =
ctx.expectedAssetsX18.sub(ctx.expectedAssetsX18.mul(ud60x18(ctx.redeemFee)));
ctx.sharesMinusRedeemFeesX18 =
getVaultAssetSwapRate(vaultId, ctx.expectedAssetsMinusRedeemFeeX18.intoUint256(), false);
ctx.sharesFees = ctx.shares - ctx.sharesMinusRedeemFeesX18.intoUint256();
ctx.creditCapacityBeforeRedeemUsdX18 = vault.getTotalCreditCapacityUsd();
ctx.lockedCreditCapacityBeforeRedeemUsdX18 = vault.getLockedCreditCapacityUsd();
address indexToken = vault.indexToken;
uint256 assets =
IERC4626(indexToken).redeem(ctx.sharesMinusRedeemFeesX18.intoUint256(), msg.sender, address(this));
if (ctx.sharesFees > 0) {
IERC4626(indexToken).redeem(
ctx.sharesFees, marketMakingEngineConfiguration.vaultDepositAndRedeemFeeRecipient, address(this)
);
}
if (assets < minAssets) revert Errors.SlippageCheckFailed(minAssets, assets);
if (assets == 0) revert Errors.RedeemMustReceiveAssets();
@>
if (
@> ctx.creditCapacityBeforeRedeemUsdX18.sub(vault.getTotalCreditCapacityUsd()).lte(
ctx.lockedCreditCapacityBeforeRedeemUsdX18.intoSD59x18()
)
) {
revert Errors.NotEnoughUnlockedCreditCapacity();
}
withdrawalRequest.fulfilled = true;
emit LogRedeem(vaultId, msg.sender, ctx.sharesMinusRedeemFeesX18.intoUint256());
}
According to the comment in the function if the credit capacity delta is greater than the locked credit capacity before the state transition, the function should revert. The problem is that the function does the opposite. The function checks if the credit capacity delta is less than or equal the locked credit capacity before redeem and if it is true, the function reverts. This contradicts the comment and allows the function to continue with its execution in case when the credit capacity delta is greater than the lockedCreditCapacityBeforeRedeemUsdX18.
The function will not revert when the credit capacity delta is greater than the locked credit capacity before the state transition. This means there will be not enough unlocked credit capacity.