# MultiTransferSwap: refund logic flaw drains ETH via malicious tokens

MultiTransferSwap's multiSwapETHForExactTokens refunded excess ETH based only on the final loop iteration, letting an attacker use malicious tokens and a flash loan to drain 0.34 ETH.

- Payout: Real-world hack
- Severity: high
- Program: multitransferswap
- Credited: DeFiHackLabs
- Disclosed: 2025-04-27
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-04/multitransferswap_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250427-multitransferswap
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high technique:chained vuln:accounting-error vuln:business-logic vuln:flash-loan

**Target:** MultiTransferSwap contract (multiSwapETHForExactTokens)
**Root cause:** The function refunds excess ETH using only the final iteration's amounts[0] instead of the total ETH spent across all iterations, so intermediate overpayments are not accounted for.
**Steps:**
1. Flash-swap WETH from LINK/WETH pair for victim balance + 0.01 ETH + 139256 wei.
2. Deploy malicious ERC20 token with controllable balanceOf and transfer that inflates pair balance.
3. Seed a Uniswap V2 WETH/token pair with 20000 wei ETH and tokenSeed = amountOut + 20000.
4. Call victim.multiSwapETHForExactTokens{value: address(this).balance}(2, amountOut, [WETH, token], victim).
5. Victim buys exact tokens twice; due to malicious token, final amounts[0] is tiny, so victim refunds most of msg.value.
6. Remove liquidity from the malicious pair, repay flash swap (amount1 + 0.4%), and forward profit.
**How found:** Likely identified by reviewing the refund logic in multiSwapETHForExactTokens and noticing it uses only the final loop's amounts[0] instead of summing total spent ETH, then crafting malicious tokens to manipulate the final input amount.
**Exploitation:** Attacker flash-borrows WETH, creates a malicious token and Uniswap pair, then calls multiSwapETHForExactTokens with a large msg.value. The victim's flawed refund logic returns almost all ETH because it only checks the last iteration's input amount. Attacker removes liquidity, repays flash loan, and keeps the drained ETH.
**Insight:** When a function loops over swaps and refunds excess ETH, verify it accumulates total spent across all iterations, not just the last one; malicious tokens can manipulate reported amounts to make the final input appear tiny.
