# Aave ParaSwapRepayAdapter: arbitrary call drains leftover swap tokens

Arbitrary-call flaw in Aave's ParaSwapRepayAdapter let attacker route swap calldata to withdraw() and drain ~$56K of leftover tokens across chains.

- Payout: Real-world hack
- Severity: high
- Program: AAVE
- Credited: DeFiHackLabs
- Disclosed: 2024-08-28
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2024-08/AAVE_Repay_Adapter.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20240828-aave-repay-adapter
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:chained vuln:access-control vuln:business-logic

**Target:** ParaSwapRepayAdapter periphery contract (swapAndRepay)
**Root cause:** The adapter passed user-supplied paraswapData callees/exchangeData into an arbitrary external call without validating the target, so attacker-controlled calldata could invoke withdraw() on the adapter itself.
**Steps:**
1. Flash loan max WBTC, wstETH(LIDO), USDT from Balancer Vault `0xBA12...F2C8`.
2. Supply WBTC and 2x adapter's wstETH balance to Aave V3 Pool `0x8787...4E2`, enable as collateral.
3. Borrow USDT to create artificial debt so swapAndRepay has something to repay.
4. Call `swapAndRepay(...)` with `paraswapData` whose `callees[0]=address(this)` and `exchangeData=abi.encodeWithSignature("withdraw(address,uint256)", USDT, calcBorrowUSDT)`, startIndexes `[0,68]`.
5. Adapter executes the arbitrary call, invoking withdraw() to pull its USDT/wstETH/WBTC balances to attacker.
6. Repay flash loan and keep the drained leftover tokens.
**How found:** Researcher (Chaofan Shou/Fuzzland) noticed the adapter holds leftover tokens from positive slippage and that swapAndRepay forwards user-controlled callees/exchangeData to arbitrary targets, enabling a self-call to withdraw().
**Exploitation:** Attacker flash-loaned large balances to satisfy collateral/debt preconditions, then abused the unvalidated callee in paraswapData to make the adapter call withdraw() on itself, siphoning accumulated positive-slippage tokens; repeated across Ethereum, Arbitrum, Polygon, Optimism, Avalanche for ~$56K total.
**Escalation:** Same primitive replayed across multiple chains/adapters to aggregate ~$56K.
**Insight:** Periphery adapters that forward user-supplied callee arrays (Paraswap/1inch-style) are arbitrary-call sinks; check whether the adapter itself holds token balances and whether withdraw()/transfer() can be reached via the forwarded calldata.
