# DUCKVADER: free mint via buyTokens(0) drained Uniswap pool

DUCKVADER's buyTokens(0) allowed free token minting; attacker looped it across fresh contracts, then sold tokens to Uniswap for ~5 ETH.

- Payout: Real-world hack
- Severity: high
- Program: DUCKVADER
- Credited: DeFiHackLabs
- Disclosed: 2025-03-11
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-03/DUCKVADER_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250311-duckvader
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** ERC20 token buyTokens function on Base
**Root cause:** buyTokens accepted a zero payment amount and still minted/transferred tokens, so tokens could be acquired for free.
**Steps:**
1. Fork Base at block 27445834.
2. Deploy AttackContract2 and call `buyTokens(0)` to obtain tokens for free, then transfer them to the parent contract.
3. Repeat with fresh AttackContract2 instances (loop of 10) to accumulate tokens.
4. Call `buyTokens(0)` again on the main contract and `approve(UNISWAP_ROUTER, max)`.
5. Swap all tokens for WETH via `swapExactTokensForETHSupportingFeeOnTransferTokens` with path [DUCKVADER, wETH].
**Exploitation:** Attacker minted tokens for free by calling buyTokens with zero payment, accumulated them across multiple contracts, then dumped them into the Uniswap V2 DUCKVADER/WETH pool for ~5 ETH.
**Escalation:** Looping fresh contracts to multiply free mints before the dump.
**Insight:** Token sale functions that take a payment amount parameter must reject zero/insufficient payment; test buy/sell entrypoints with amount=0 and msg.value=0 to check for free minting.
