`PrizeVault::claimYieldFeeShares(uint256 _shares)` always reduces `yieldFeeBalance` to zero, leaving funds stuck in the yield vault if `_shares < yieldFeeBalance`.  
Audit: 2024-03-pooltogether-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-03-pooltogether/blob/main/pt-v5-vault/src/PrizeVault.sol#L611


# Vulnerability details

**Impact:** 
The function `claimYieldFeeShares` allows the `yieldFeeRecipient` to claim shares corresponding to assets in `yieldVault`. However regardless of the amount of `_shares` they request (providing `_shares <= yieldFeeBalance`), the `yieldFeeBalance` gets reset to zero, meaning any access to the remaining assets in `yieldVault` is permanently lost in cases where `_shares < yieldFeeBalance`.

This is likely caused by the function mistakenly subtracting the entire `yieldFeeBalance` from itself, rather than `_shares`:

```diff
-   yieldFeeBalance -= _yieldFeeBalance;`
+   yieldFeeBalance -= _shares;
```

**Proof of Concept:**
Add the following test to `PrizeVault.t.sol` to confirm that `yieldFeeRecipient`'s tokens in the underlying yield vault become unredeemable:
```solidity
    function test_YieldFeeBalanceAlwaysReturnsToZero() public {
        vault.setYieldFeePercentage(1e8); // 10%
        vault.setYieldFeeRecipient(bob);
        assertEq(vault.totalDebt(), 0);

        // Make an initial deposit
        underlyingAsset.mint(alice, 1e18);
        vm.startPrank(alice);
        underlyingAsset.approve(address(vault), 1e18);
        vault.deposit(1e18, alice);
        vm.stopPrank();

        // Add funds to liquidiate
        underlyingAsset.mint(address(vault), 1e18);
        vault.setLiquidationPair(address(this));
        uint256 maxLiquidation = vault.liquidatableBalanceOf(address(underlyingAsset));
        uint256 amountOut = maxLiquidation;
        vault.transferTokensOut(address(0), bob, address(underlyingAsset), amountOut);

        // Confirm there are now fees to be claimed
        vm.startPrank(bob);
        uint256 claimableFees = vault.yieldFeeBalance();
        assert(claimableFees > 1);

        // Bob claims some amount less than yieldFeeBalance
        vault.claimYieldFeeShares(1);

        // Confirm yieldFeeBalance gets set back to zero despite not claiming all
        assertEq(vault.yieldFeeBalance(), 0);


        // Bob withdraws
        uint256 bobBalance = vault.balanceOf(bob);
        vault.redeem(bobBalance, bob, bob);
        vm.stopPrank();
        checkInvariants();

        // Confirm the left over claimableFees are in the contract
        assert(underlyingAsset.balanceOf(address(vault)) >= claimableFees - 1);

        // Alice withdraws
        uint256 aliceBalance = vault.balanceOf(alice);
        vm.startPrank(alice);
        vault.redeem(aliceBalance, alice, alice);
        vm.stopPrank();

        // Confirm assets in the contract were used cover Alice's redeem
        assertEq(underlyingAsset.balanceOf(address(vault)), 0);
        // Confirm there are still assets in the vault (Alice's deposited 1e18 - the balance that was in the contract)
        assert(vault.totalAssets() >= claimableFees - 1);
        console.log("Total Assets in yield vault", vault.totalAssets(