# RevertFinance V3Utils: arbitrary external call drains token allowances

RevertFinance V3Utils trusted an attacker-supplied swapRouter address, letting arbitrary calls drain USDC allowances users had left on the contract (~$30k).

- Payout: Real-world hack
- Severity: high
- Program: - RevertFinance
- Analysis by: DeFiHackLabs
- Disclosed: 2023-02-18
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-02/RevertFinance_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20230218-revertfinance
- Tags: area:web3 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:** V3Utils atomic-swap contract (Uniswap V3 aggregator integration)
**Root cause:** V3Utils.swap took the router/approval target from aggregator API response data without validation, so any address (e.g. USDC) could be passed as swapRouter and called with V3Utils as msg.sender.
**Steps:**
1. Victim approves V3Utils (0x531110418d8591C92e9cBBFC722Db8FFb604FAFD) for more USDC than actually swapped, leaving residual allowance.
2. Attacker builds SwapParams with tokenIn/tokenOut = attacker contract, amountIn=1, minAmountOut=0, recipient=attacker, and swapData = `abi.encode(address(USDC), address(this), abi.encodeWithSignature("transferFrom(address,address,uint256)", victim, attacker, amount))`.
3. Attacker calls `utils.swap(params)`; V3Utils uses the attacker-supplied router (USDC) as the call target with itself as caller.
4. USDC.transferFrom pulls the victim's residual allowance to the attacker; repeat per victim.
**How found:** Team used Tenderly to trace reported transactions and noticed interaction with a suspicious unverified freshly-deployed contract; inspecting calldata showed swapRouter parameter set to the USDC token contract, revealing the arbitrary-call vector.
**Exploitation:** No capital needed: attacker only needed pre-existing allowances to V3Utils. By making the token contract itself the 'router', V3Utils executed transferFrom on behalf of the victim's approval, siphoning ~$30k across mainnet, Polygon, Optimism and Arbitrum before the team disabled the feature.
**Insight:** When a contract takes a router/approver address from off-chain API data, treat it as attacker-controlled: any token with user allowances becomes a call target, so check whether the callee is invoked with the protocol as msg.sender.

