# RWAVault: missing ERC4626 allowance check drains depositor USDC

RWAVault's ERC4626 withdraw override skipped allowance checks, letting an attacker drain eight depositors' USDC shares to an arbitrary receiver for ~398k USDC.

- Payout: Real-world hack
- Severity: critical
- Program: RWAVault
- Credited: DeFiHackLabs
- Disclosed: 2026-04-28
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2026-04/RWAVault_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20260428-rwavault
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** ERC4626 vault withdraw() override on Ethereum mainnet
**Root cause:** RWAVault overrode ERC4626 withdraw() without spending allowance when msg.sender != owner, so anyone could withdraw on behalf of any depositor to an arbitrary receiver.
**Steps:**
1. Identify vault entry 0xB9c7...f88a and its withdraw override lacking allowance spend.
2. For each of 8 victim addresses call `vault.withdraw(requestedAssets[i], address(this), victims[i])` with no approval.
3. Approve Uniswap V2 router and `swapExactTokensForETH(5_000e6, 0, [USDC,WETH], BLOCK_MINER, deadline)` to bribe the block builder.
4. Transfer remaining USDC to attacker EOA.
**How found:** Code review of the vault's ERC4626 override revealed withdraw() omitted the allowance check required when caller != owner, enabling third-party withdrawals.
**Exploitation:** Attacker contract called withdraw() eight times specifying victim owners and itself as receiver, pulling ~398,655 USDC of vault assets without any allowance. 5,000 USDC was swapped to ETH and paid to the block beneficiary as a bribe; the rest forwarded to the attacker EOA.
**Escalation:** Bribed the block miner/beneficiary with ETH to secure inclusion of the draining transaction.
**Insight:** When auditing ERC4626 forks, diff every overridden function (withdraw/redeem/transferFrom) against the spec's allowance semantics; a single missing `_spendAllowance` turns any depositor into a victim of arbitrary-receiver withdrawals.
