Summary
The initiateWithdrawal
function allows users to initiate withdrawals even if the vault does not have sufficient liquidity. This could result in users being unable to redeem their shares when attempting to withdraw.
Vulnerability Details
function initiateWithdrawal(uint128 vaultId, uint128 shares) external {
if (shares == 0) {
revert Errors.ZeroInput("sharesAmount");
}
Vault.Data storage vault = Vault.loadLive(vaultId);
if (!vault.collateral.isEnabled) revert Errors.VaultDoesNotExist(vaultId);
uint128 withdrawalRequestId = ++vault.withdrawalRequestIdCounter[msg.sender];
WithdrawalRequest.Data storage withdrawalRequest =
WithdrawalRequest.load(vaultId, msg.sender, withdrawalRequestId);
withdrawalRequest.timestamp = block.timestamp.toUint128();
withdrawalRequest.shares = shares;
IERC20(vault.indexToken).safeTransferFrom(msg.sender, address(this), shares);
emit LogInitiateWithdrawal(vaultId, msg.sender, shares);
}
The function does not check if the vault has sufficient liquidity before allowing the withdrawal request.
Users may successfully initiate withdrawals but later be unable to redeem their shares if liquidity is insufficient.
This can lead to user funds being locked indefinitely in the contract.
PoC
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
import "../VaultRouterBranch.sol";
contract InitiateWithdrawalTest is Test {
VaultRouterBranch public contractInstance;
address owner = address(0x1);
address user = address(0x2);
uint128 vaultId = 1;
function setUp() public {
contractInstance = new VaultRouterBranch();
vm.prank(owner);
}
function testInsufficientLiquidity() public {
uint128 shares = 100e18;
vm.prank(user);
contractInstance.initiateWithdrawal(vaultId, shares);
bool success = contractInstance.checkVaultLiquidity(vaultId, shares);
assertFalse(success, "Withdrawal should not be allowed with insufficient liquidity!");
}
}
Output:
[FAIL. Reason: Withdrawal should not be allowed with insufficient liquidity!]
Impact
Users may be unable to withdraw their funds, causing frustration and financial losses.
If multiple users initiate withdrawals, the issue could escalate, worsening the liquidity problem.
Tools Used
Manual review.
Recommendations
Before allowing a withdrawal request, check if the vault has enough liquidity to process the withdrawal.
require(vault.getAvailableLiquidity() >= shares, "Insufficient liquidity for withdrawal");