# WGPT: business logic flaw drained via flash-loan swap loop

WGPT token's burn/swap business logic on BSC was abused via flash loans and a fake token pair to drain ~$80k of BUSDT.

- Payout: Real-world hack
- Severity: high
- Program: WGPT
- Analysis by: DeFiHackLabs
- Disclosed: 2023-07-12
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-07/WGPT_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20230712-wgpt
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:chained vuln:accounting-error vuln:business-logic vuln:flash-loan

**Target:** BEP-20 token contract and its PancakeSwap pair
**Root cause:** WGPT's burnToken/isSwap/burnRate logic interacts incorrectly with its liquidity pair, letting an attacker manipulate pair reserves and skim value out of the WGPT/BUSDT pool.
**Steps:**
1. Flash-borrow BUSDT across DPPOracle1-3, DPP, DPPAdvanced and PancakeV3 pool.
2. Create/seed attacker-controlled ExpToken and BUSDT_ExpToken pair, call `BUSDT_ExpToken.swap(...)` to trigger `pancakeCall`.
3. In `pancakeV3FlashCallback`, swap 200k BUSDT into WGPT via Router, then loop `WGPT.transferFrom(this, WGPT_BUSDT, balance/99)` + `WGPT_BUSDT.skim(this)` while `WGPT_BUSDT.totalSupply() > 100_200e18`.
4. Swap accumulated WGPT back to BUSDT via `WGPT_BUSDT.swap(0, amounts[1], this, '')`.
5. Repay flash loans and keep the BUSDT profit.
**How found:** Likely spotted that WGPT's burnToken/isSwap/burnRate logic could be triggered to distort pair accounting, then tested a transfer+skim loop against the pair.
**Exploitation:** Attacker flash-loaned large BUSDT liquidity, manipulated the WGPT/BUSDT pair through repeated transfer+skim iterations exploiting the burn logic, then swapped the inflated WGPT balance back to BUSDT and repaid loans, netting ~$80k.
**Escalation:** Chained five flash-loan sources plus a PancakeV3 flash to maximize capital for the reserve manipulation loop.
**Insight:** Tokens with custom burn/swap hooks that read pair reserves or totalSupply can be drained by iterating transfer+skim against their own pair; watch for loops where totalSupply gates the exploit window.

