# ArbitrumBaseSwapper: public swap refunds full balance to attacker

Public swapTokensForExactTokens on ArbitrumBaseSwapper let attacker set recipient and drain the contract's full token1 balance via refund, netting ~$1.8k.

- Payout: Real-world hack
- Severity: high
- Program: ArbitrumBaseSwapper
- Credited: DeFiHackLabs
- Disclosed: 2025-08-08
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-08/ArbitrumBaseSwapper_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250808-arbitrumbaseswapper
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** BaseSwapperUniswapV3 swap contract on Arbitrum
**Root cause:** swapTokensForExactTokens is publicly callable and, after the router consumes only part of the max input, refunds the contract's entire remaining token1 balance to a caller-controlled recipient.
**Steps:**
1. Call `swapTokensForExactTokens(address(this), VICTIM_TOKEN, USDC, 472997613026749247557538, 100)` on BaseSwapperUniswapV3 with attacker as recipient.
2. Router spends only a tiny amount of VICTIM_TOKEN for 100 USDC exact output; swapper refunds its full remaining VICTIM_TOKEN balance to attacker.
3. Approve Uniswap V3 router for drained VICTIM_TOKEN and `exactInputSingle` VICTIM_TOKEN->WETH fee 3000.
4. Unwrap WETH via `withdraw` and receive ETH.
**Exploitation:** Attacker directly invoked the public swap with itself as recipient and a huge max input but tiny exact USDC output, causing the swapper to refund its entire token1 balance; then swapped drained tokens to WETH and withdrew ETH.
**Insight:** On swap-wrapper contracts, check whether exact-output paths refund the contract's whole remaining input balance to a caller-supplied recipient; a tiny exact-output request with a huge max input can drain the wrapper's own token holdings.
