# UPS: transfer-to-pair logic flaw enables reserve manipulation drain

UPS token's transfer to its PancakeSwap pair didn't update reserves, letting attacker skim and swap to drain ~$28K via flash loan.

- Payout: Real-world hack
- Severity: high
- Program: UPS
- Analysis by: DeFiHackLabs
- Disclosed: 2024-04-09
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2024-04/UPS_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20240409-ups
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm vuln:accounting-error vuln:business-logic

**Target:** UPS token contract and PancakeSwap V2 pair
**Root cause:** Transferring UPS tokens directly to the pair contract does not update the pair's reserves, so the attacker can repeatedly skim and swap to extract value.
**Steps:**
1. Flash loan 3.5M USDT from PancakeSwap V3 pool `0x4f31...`.
2. Transfer 2M USDT to UPS/USDT pair `0xA263...` and call `sync()` to inflate reserves.
3. Swap 1M USDT for UPS via router.
4. Loop 10 times: transfer min(attacker UPS balance, pair UPS balance) to pair, then call `skim(address(this))` to recover excess UPS.
5. Loop 3 times: transfer all UPS balance to pair, compute `amountOut = router.getAmountOut(transfer_amount - r0, r0, r1)`, call `pair.swap(0, amountOut, attacker, '')`.
6. Repay flash loan 3.5M USDT + fee.
**How found:** Likely identified that UPS token transfers to the pair do not trigger reserve updates, enabling skim-based arbitrage.
**Exploitation:** Attacker used a flash loan to manipulate the UPS/USDT pair reserves via direct transfers that bypassed reserve updates, then repeatedly skimmed and swapped to drain USDT from the pair.
**Insight:** Check if token transfers to a pair contract update reserves; if not, repeated skim/swap cycles can drain the pair.
