MEDIUM severity: Yield tokens can be permanently locked in the vault when all stakers withdraw during vesting window. **Description:** Yield tokens can be permanently locked in the vault when all stakers withdraw during vesting window.

**Proof of Concept:** Add test to `StakingVaultTest.t.sol`:

**Recommended Mitigation:** Don't allow all shares to be withdrawn; a common technique is on the first deposit to mint.....

Vulnerable code:
function test_allStakersWithdrawDuringVestingWindow_LockedTokensInVault() public {
    // Start fresh - check initial state
    assertEq(vault.totalSupply(), 100 ether); // Owner already has 100 from setup

    // Setup: 2 more stakers
    address staker1 = address(0x1);
    address staker2 = address(0x2);

    uint256 stakeAmount = 100 ether;

    // Setup stakers
    vm.startPrank(owner);
    sbtContract.setVerified(staker1, true);
    sbtContract.setVerified(staker2, true);
    asset.mint(staker1, stakeAmount);
    asset.mint(staker2, stakeAmount);
    vm.stopPrank();

    // Each stakes 100 HILBTC
    vm.prank(staker1);
    asset.approve(address(vault), stakeAmount);
    vm.prank(staker1);
    vault.stake(stakeAmount);

    vm.prank(staker2);
    asset.approve(address(vault), stakeAmount);
    vm.prank(staker2);
    vault.stake(stakeAmount);

    // Vault now has 300 HILBTC total (100 owner + 200 from stakers), 300 shares
    assertEq(vault.totalSupply(), 300 ether);
    assertEq(asset.balanceOf(address(vault)), 300 ether);

    // Owner distributes 30 HILBTC yield
    vm.startPrank(owner);
    asset.approve(address(vault), 30 ether);
    vault.distributeYield(30 ether, block.timestamp);
    vm.stopPrank();

    // After 4 hours (50% vested)
    vm.warp(block.timestamp + 4 hours);

    console.log("Before withdrawals:");
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Unvested:", vault.getUnvestedAmount());
    console.log("Total assets:", vault.totalAssets());
    console.log("Total shares:", vault.totalSupply());

    // Owner withdraws their 100 shares
    vm.prank(owner);
    vault.redeem(100 ether, owner, owner);

    console.log("\nAfter owner withdrawal:");
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Unvested:", vault.getUnvestedAmount());
    console.log("Total assets:", vault.totalAssets());
    console.log("Total shares:", vault.totalSupply());

    // Check if remaining stakers can withdraw
    uint256 staker1Shares = vault.balanceOf(staker1);
    uint256 maxRedeem1 = vault.maxRedeem(staker1);
    console.log("\nStaker1 shares:", staker1Shares);
    console.log("Max redeemable:", maxRedeem1);

    // Try withdrawal
    vm.prank(staker1);
    vault.redeem(staker1Shares, staker1, staker1);

    console.log("\nAfter staker1 withdrawal:");
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Total assets:", vault.totalAssets());
    console.log("Total shares:", vault.totalSupply());

    // Can staker2 still withdraw?
    uint256 staker2Shares = vault.balanceOf(staker2);
    uint256 maxRedeem2 = vault.maxRedeem(staker2);
    console.log("\nStaker2 shares:", staker2Shares);
    console.log("Max redeemable:", maxRedeem2);
    console.log("Would receive:", vault.previewRedeem(staker2Shares));

    // Final withdrawal
    vm.prank(staker2);
    vault.redeem(staker2Shares, staker2, staker2);

    console.log("\nFinal state:");
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Total shares:", vault.totalSupply());

    // Wait for vesting to complete
    vm.warp(block.timestamp + 4 hours); // Now 8 hours total

    console.log("\nAfter vesting completes:");
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Unvested:", vault.getUnvestedAmount());

    // 15000000000000000001 still locked in the vault
    console.log("Total assets:", vault.totalAssets());
    // 0 shares
    console.log("Total supply:", vault.totalSupply());

    // Owner deposits 100 HILBTC
    vm.startPrank(owner);
    asset.approve(address(vault), 100 ether);
    uint256 sharesReceived = vault.deposit(100 ether, owner);
    vm.stopPrank();

    console.log("\nAfter owner re-deposits 100 HILBTC:");
    console.log("Shares received:", sharesReceived);
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Total assets:", vault.totalAssets());
    console.log("Share price:", vault.totalAssets() * 1e18 / vault.totalSupply());

    // Owner withdraws all
    vm.prank(owner);
    uint256 withdrawn = vault.redeem(sharesReceived, owner, owner);

    console.log("\nOwner withdrew:", withdrawn);
    // 16428571428571428571 still locked in the vault greater than
    // 15000000000000000001 previously locked!
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    // 0 shares
    console.log("Total shares:", vault.totalSupply());
}

function test_vestingWithDeadShares() public {
    // Simulate the dead shares implementation
    uint256 DEAD_SHARES = 10000;

    // First deposit by owner triggers dead shares
    vm.startPrank(owner);
    asset.approve(address(vault), 100 ether);
    vault.stake(100 ether);

    // Simulate minting dead shares (in reality this would be in deposit function)
    uint256 actualOwnerShares = vault.balanceOf(owner);
    console.log("Owner shares received:", actualOwnerShares);
    console.log("Total supply (includes dead shares):", vault.totalSupply() + DEAD_SHARES);
    assertEq(actualOwnerShares + DEAD_SHARES, vault.totalSupply());
    vm.stopPrank();

    // Setup 2 more stakers
    address staker1 = address(0x1);
    address staker2 = address(0x2);

    uint256 stakeAmount = 100 ether;

    // Setup and stake
    vm.startPrank(owner);
    asset.mint(staker1, stakeAmount);
    asset.mint(staker2, stakeAmount);
    vm.stopPrank();

    vm.startPrank(staker1);
    asset.approve(address(vault), stakeAmount);
    vault.stake(stakeAmount);
    vm.stopPrank();

    vm.startPrank(staker2);
    asset.approve(address(vault), stakeAmount);
    vault.stake(stakeAmount);
    vm.stopPrank();

    // Current state: 300 HILBTC deposited, 300 shares (+ 1000 dead shares)
    uint256 totalUserShares = vault.totalSupply(); // This would be 1300 with dead shares
    console.log("\nBefore yield distribution:");
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Total user shares:", totalUserShares);

    // Owner distributes 30 HILBTC yield
    vm.startPrank(owner);
    asset.approve(address(vault), 30 ether);
    vault.distributeYield(30 ether, block.timestamp);
    vm.stopPrank();

    // After 4 hours (50% vested)
    vm.warp(block.timestamp + 4 hours);

    console.log("\nDuring vesting (4 hours):");
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Unvested amount:", vault.getUnvestedAmount());
    console.log("Total assets:", vault.totalAssets());

    // All users withdraw during vesting
    uint256 ownerShares = vault.balanceOf(owner);
    vm.prank(owner);
    vault.redeem(ownerShares, owner, owner);

    uint256 staker1Shares = vault.balanceOf(staker1);
    vm.prank(staker1);
    vault.redeem(staker1Shares, staker1, staker1);

    uint256 staker2Shares = vault.balanceOf(staker2);
    vm.prank(staker2);
    vault.redeem(staker2Shares, staker2, staker2);

    console.log("\nAfter all users withdraw:");
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Unvested amount:", vault.getUnvestedAmount());
    console.log("Total assets:", vault.totalAssets());
    console.log("Remaining shares (should be just dead shares):", vault.totalSupply());

    // Wait for vesting to complete
    vm.warp(block.timestamp + 4 hours);

    console.log("\nAfter vesting completes:");
    // 15000000000000010501 tokens locked in vault
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Unvested amount:", vault.getUnvestedAmount());
    console.log("Total assets:", vault.totalAssets());
    // only 10000 dead shares remain
    console.log("Dead shares remain:", vault.totalSupply());

    // New user tries to deposit and recover locked funds
    address newUser = address(0x3);
    vm.startPrank(owner);
    asset.mint(newUser, 100 ether);
    vm.stopPrank();

    vm.startPrank(newUser);
    asset.approve(address(vault), 100 ether);
    uint256 sharesReceived = vault.deposit(100 ether, newUser);

    console.log("\nNew user deposits 100 HILBTC:");
    // 66673
    console.log("Shares received:", sharesReceived);
    // 115000000000000010501
    console.log("Vault balance:", asset.balanceOf(address(vault)));
    console.log("Total assets:", vault.totalAssets());

    // New user immediately withdraws to see how much they can recover
    uint256 withdrawAmount = vault.redeem(sharesReceived, newUser, newUser);
    console.log("\nNew user withdraws all shares:");
    // user received 99999934788846293400 tokens
    console.log("Amount received:", withdrawAmount);
    // user lost 65211153706600 tokens
    console.log("Loss:", 100 ether - withdrawAmount);
    // vault locked balance increased to 15000065211153717101
    console.log("Vault balance (still locked):", asset.balanceOf(address(vault)));
    vm.stopPrank();
}

// After the operation, check if only dead shares remain
if (totalSupply() - shares == deadShares) {
    uint256 remainingUnvested = getUnvestedAmount();
    if(remainingUnvested > 0) {
        vestingAmount = 0;
        lastDistributionTimestamp = 0;
        IERC20(asset()).safeTransfer(owner(), remainingUnvested);
    }
}