Vulnerability: User's funds are locked temporarily in the PriorityPool contract
Severity: medium

Description:
The protocol intended to utilize the deposit queue for withdrawal to minimize the stake/unstake interaction with the staking pool. When a user wants to withdraw, they are supposed to call the function `PriorityPool::withdraw()` with the desired amount as a parameter.\\n```\\nfunction withdraw(uint256 _amount) external {//@audit-info LSD token\\n    if (_amount == 0) revert InvalidAmount();\\n    IERC20Upgradeable(address(stakingPool)).safeTransferFrom(msg.sender, address(this), _amount);//@audit-info get LSD token from the user\\n    _withdraw(msg.sender, _amount);\\n}\\n```\\n\\nAs we can see in the implementation, the protocol pulls the `_amount` of LSD tokens from the user first and then calls `_withdraw()` where the actual withdrawal utilizing the queue is processed.\\n```\\nfunction _withdraw(address _account, uint256 _amount) internal {\\n    if (poolStatus == PoolStatus.CLOSED) revert WithdrawalsDisabled();\\n\\n    uint256 toWithdrawFromQueue = _amount <= totalQueued ? _amount : totalQueued;//@audit-info if the queue is not empty, we use that first\\n    uint256 toWithdrawFromPool = _amount - toWithdrawFromQueue;\\n\\n    if (toWithdrawFromQueue != 0) {\\n        totalQueued -= toWithdrawFromQueue;\\n        depositsSinceLastUpdate += toWithdrawFromQueue;//@audit-info regard this as a deposit via the queue\\n    }\\n\\n    if (toWithdrawFromPool != 0) {\\n        stakingPool.withdraw(address(this), address(this), toWithdrawFromPool);//@audit-info withdraw from pool into this contract\\n    }\\n\\n    //@audit-warning at this point, toWithdrawFromQueue of LSD tokens remain in this contract!\\n\\n    token.safeTransfer(_account, _amount);//@audit-info\\n    emit Withdraw(_account, toWithdrawFromPool, toWithdrawFromQueue);\\n}\\n```\\n\\nBut looking in the function `_withdraw()`, only `toWithdrawFromPool` amount of LSD tokens are withdrawn (burn) from the staking pool and `toWithdrawFromQueue` amount of LSD tokens remain in the `PriorityPool` contract. On the other hand, the contract tracks the queued amount for users by the mapping `accountQueuedTokens` and this leads to possible mismatch in the accounting. Due to this mismatch, a user's LSD tokens can be locked in the `PriorityPool` contract while the user sees his queued amount (getQueuedTokens()) is positive. Users can claim the locked LSD tokens once the function `updateDistribution` is called. Through the communication with the protocol team, it is understood that `updateDistribution` is expected to be called probably every 1-2 days unless there were any new deposits into the staking pool. So it means user's funds can be locked temporarily in the contract which is unfair for the user.

Impact:
User's LSD tokens can be locked temporarily in the PriorityPool contract\\nProof of Concept:\\n```\\n it('Cyfrin: user funds can be locked temporarily', async () => {\\n    // try deposit 1500 while the capacity is 1000\\n    await strategy.setMaxDeposits(toEther(1000))\\n    await sq.connect(signers[1]).deposit(toEther(1500), true)\\n\\n    // 500 ether is queued for accounts[1]\\n    assert.equal(fromEther(await stakingPool.balanceOf(accounts[1])), 1000)\\n    assert.equal(fromEther(await sq.getQueuedTokens(accounts[1], 0)), 500)\\n    assert.equal(fromEther(await token.balanceOf(accounts[1])), 8500)\\n    assert.equal(fromEther(await sq.totalQueued()), 500)\\n    assert.equal(fromEther(await stakingPool.balanceOf(sq.address)), 0)\\n\\n    // at this point user calls withdraw (maybe by mistake?)\\n    // withdraw swipes from the queue and the deposit room stays at zero\\n    await stakingPool.connect(signers[1]).approve(sq.address, toEther(500))\\n    await sq.connect(signers[1]).withdraw(toEther(500))\\n\\n    // at this point getQueueTokens[accounts[1]] does not change but the queue is empty\\n    // user will think his queue position did not change and he can simply unqueue\\n    assert.equal(fromEther(await stakingPool.balanceOf(accounts[1])), 500)\\n    assert.equal(fromEther(await sq.getQueuedTokens(accounts[1], 0)), 500)\\n    assert.equal(fromEther(await token.balanceOf(accounts[1])), 9000)\\n    assert.equal(fromEther(await sq.totalQueued()), 0)\\n    // NOTE: at this point 500 ethers of LSD tokens are locked in the queue contract\\n    assert.equal(fromEther(await stakingPool.balanceOf(sq.address)), 500)\\n\\n    // but unqueueTokens fails because actual totalQueued is zero\\n    await expect(sq.connect(signers[1]).unqueueTokens(0, 0, [], toEther(500))).to.be.revertedWith(\\n      'InsufficientQueuedTokens()'\\n    )\\n\\n    // user's LSD tokens are still locked in the queue contract\\n    await stakingPool.connect(signers[1]).approve(sq.address, toEther(500))\\n    await sq.connect(signers[1]).withdraw(toEther(500))\\n    assert.equal(fromEther(await stakingPool.balanceOf(accounts[1])), 0)\\n    assert.equal(fromEther(await sq.getQueuedTokens(accounts[1], 0)), 500)\\n    assert.equal(fromEther(await token.balanceOf(accounts[1])), 9500)\\n    assert.equal(fromEther(await sq.totalQueued()), 0)\\n    assert.equal(fromEther(await stakingPool.balanceOf(sq.address)), 500)\\n\\n    // user might try withdraw again but it will revert because user does not have any LSD tokens\\n    await stakingPool.connect(signers[1]).approve(sq.address, toEther(500))\\n    await expect(sq.connect(signers[1]).withdraw(toEther(500))).to.be.revertedWith(\\n      'Transfer amount exceeds balance'\\n    )\\n\\n    // in conclusion, user's LSD tokens are locked in the queue contract and he cannot withdraw them\\n    // it is worth noting that the locked LSD tokens are credited once updateDistribution is called\\n    // so the lock is temporary\\n  })\\n```\\n

Recommended mitigation:
Consider add a feature to allow users to withdraw LSD tokens from the contract directly.