# VouchFaucet can be immediately drained by anyone

VouchFaucet's claimTokens never updates claimedTokens mapping, so anyone can drain all tokens despite maxClaimable limit.

- Payout: Contest reward
- Severity: high
- Program: Union Finance Update 2
- Credited: 0xAadi
- Disclosed: 2024-06-12
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2024-06-union-finance-update-2-judging/issues/33
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-06-union-finance-update-2%3AH-2
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high technique:source-review vuln:access-control vuln:business-logic

**Target:** VouchFaucet smart contract
**Root cause:** claimTokens checks claimedTokens[token][msg.sender] <= maxClaimable[token] but never updates claimedTokens, so the check always passes (0 <= maxClaimable).
**Steps:**
1. Deploy VouchFaucet with any maxClaimable > 0.
2. Mint tokens to the faucet contract.
3. Call `claimTokens(token, amount)` with amount exceeding maxClaimable.
4. The require passes because claimedTokens[token][msg.sender] is 0.
5. Tokens are transferred to the caller.
**How found:** Manual code review identified that the claimedTokens mapping is read but never written, making the require condition always true.
**Exploitation:** Any address calls claimTokens(token, amount) with amount equal to the contract's entire token balance; the require always passes, draining the faucet in one transaction.
**Insight:** In access control checks, verify that the state variable used in the condition is actually updated after the check; a read-only mapping in a require is a red flag.
