# Paraswap AugustusV6: unauthenticated callback drains approved tokens

Paraswap AugustusV6's uniswapV3SwapCallback lacked caller validation, letting anyone drain tokens from users who approved the contract.

- Payout: Real-world hack
- Severity: high
- Program: Paraswap
- Analysis by: DeFiHackLabs
- Disclosed: 2024-03-20
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2024-03/Paraswap_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20240320-paraswap
- 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:** AugustusV6 swap router contract
**Root cause:** The uniswapV3SwapCallback function is externally callable and does not verify that the caller is a legitimate Uniswap pool or that the swap was initiated by the contract, allowing arbitrary data to drive token transfers from users who approved AugustusV6.
**Steps:**
1. Identify victim address with token approval to AugustusV6 (e.g., 0x0cc396F558aAE5200bb0aBB23225aCcafCA31E27).
2. Craft callback data encoding: recipient=attacker, from=victim, tokenIn=wTAO, tokenOut=WETH, fee1=3000, encodedOPSECAddr (0x80...6a7e...), tokenOut2=WETH, fee2=10000.
3. Call `AugustusV6.uniswapV3SwapCallback(0, 10e18, data)` directly from attacker contract.
4. Contract transfers victim's OPSEC (via approval) and outputs WETH to attacker.
**How found:** Likely identified that uniswapV3SwapCallback was externally callable without verifying msg.sender as a Uniswap pool, and that user approvals to AugustusV6 could be abused by supplying arbitrary 'from' addresses in the callback data.
**Exploitation:** Attacker directly invokes the public uniswapV3SwapCallback with crafted parameters. The callback logic uses the victim's existing approval to AugustusV6 to transfer OPSEC from the victim, swaps it, and sends WETH to the attacker. A whitehat frontran the original attack transaction.
**Insight:** In DeFi routers, any public callback or swap-execution function that pulls tokens via user approvals must authenticate the caller (e.g., check msg.sender is a known pool) and bind the swap parameters to an initiated swap; otherwise arbitrary 'from' addresses can be drained.
