# Griefing attack on the Vaults is possible, withdrawing the winning side stakes

Vault withdraw checks isApprovedForAll(owner, receiver) instead of caller, letting anyone force-withdraw a user's winning-side stake at epoch end.

- Payout: Contest reward
- Severity: high
- Program: Y2k Finance
- Credited: hyh
- Disclosed: 2023-01-09
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-09-y2k-finance-findings/issues/434
- Library page: https://bugbountylibrary.com/r/c4%3A2022-09-y2k-finance%3AH-06
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** SemiFungibleVault/Vault withdraw()
**Root cause:** Withdraw authorization checks isApprovedForAll(owner, receiver) rather than the caller (msg.sender), so any approved receiver address lets an arbitrary third party trigger withdrawal.
**Steps:**
1. Two depositors Bob and David mutually approve each other (isApprovedForAll).
2. Attacker Mike observes epoch ending with no depeg (winning side determined).
3. In the last block of the epoch, Mike calls `withdraw(id, assets, receiver=Bob, owner=Bob)` and same for David.
4. require passes because isApprovedForAll(owner, receiver) is true; funds withdrawn to receiver before payout.
**How found:** Code reading of withdraw() in SemiFungibleVault and Vault: noticed the approval check references receiver instead of msg.sender, meaning caller identity is never validated against the approval.
**Exploitation:** Attacker calls withdraw() for victims who have any approved receiver, forcing early withdrawal at epoch end so they forfeit the guaranteed winning-side payoff; attacker gains nothing but sabotages victims.
**Insight:** In ERC4626-style withdraw(owner, receiver) functions, verify the approval is on msg.sender (the spender), not on receiver; a receiver-based check lets any third party act on the owner's behalf.
