# LiFi Diamond: arbitrary call in depositToGasZipERC20 drains USDT approvals

LiFi Diamond's depositToGasZipERC20 lacked input validation, letting attacker pass arbitrary callData to USDT.transferFrom and drain ~10M USD from a victim's approval.

- Payout: Real-world hack
- Severity: critical
- Program: Lifiprotocol
- Credited: DeFiHackLabs
- Disclosed: 2024-07-16
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2024-07/Lifiprotocol_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20240716-lifiprotocol
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:critical tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** LiFiDiamond contract (depositToGasZipERC20) on Ethereum mainnet
**Root cause:** depositToGasZipERC20 accepted a LibSwap.SwapData struct and executed swapData.callData on swapData.callTo without validating that callTo/sendingAssetId matched the intended asset or that the call was a legitimate swap, allowing arbitrary external calls.
**Steps:**
1. Deploy attacker contract `Money` implementing balanceOf returning 1 and approve() that deploys `Help` and calls LiFiDiamond with 1 wei.
2. Call `LiFiDiamond.depositToGasZipERC20(swapData, 0, attacker)` with swapData: callTo=USDT, approveTo=attacker, sendingAssetId=Money, receivingAssetId=Money, fromAmount=1, callData=`transferFrom(Victim, attacker, 2276295880553)`, requiresDeposit=true.
3. LiFiDiamond executes `USDT.transferFrom(Victim, attacker, amount)` using the victim's existing USDT allowance to LiFiDiamond.
4. Attacker receives ~2.27M USDT (worth ~10M USD at the time).
**How found:** Likely identified that depositToGasZipERC20 passed user-supplied SwapData directly to an external call without validating the target or asset, and that the contract had outstanding token approvals from users.
**Exploitation:** Attacker crafted a malicious SwapData struct where callTo was USDT and callData was transferFrom(victim, attacker, amount). Because LiFiDiamond held a large USDT allowance from the victim (0xABE45...), the call succeeded, transferring victim's USDT to the attacker. No flash loan needed; the attacker used a fake token contract (Money) to satisfy balance checks.
**Insight:** When a contract executes arbitrary calldata from user input, check if it holds token approvals from other users; a single unvalidated call can drain all approved funds.
