# d3xai proxy exchange() price manipulation drains 190 BNB

d3xai proxy exchange() priced D3XAT off manipulable PancakeSwap pool, letting attacker buy low via proxy and sell high for 190 BNB.

- Payout: Real-world hack
- Severity: high
- Program: d3xai
- Credited: DeFiHackLabs
- Disclosed: 2025-08-16
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-08/d3xai_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250816-d3xai
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm technique:chained vuln:business-logic vuln:flash-loan vuln:oracle-manipulation

**Target:** D3XAT token proxy exchange() on BSC
**Root cause:** The proxy's exchange() function prices D3XAT using a spot price derived from the PancakeSwap pool, which the attacker can move by large swaps before calling exchange().
**Steps:**
1. Flash loan 20M USDT from Pancake V3 pool `0x92b7...3121`.
2. Buy D3XAT cheaply via proxy `exchange()` using ~24k USDT across 2 ProxyBuyer contracts.
3. Spend ~6.18M USDT buying D3XAT from Pancake Router across 27 buyers, pumping the pool price.
4. Sell the Step 2 D3XAT back through proxy `exchange()` at the now-inflated price, netting ~22.5k USDT.
5. Sell Step 3 D3XAT to Pancake Router for ~6.11M USDT.
6. Repay 20M USDT + flash fee to the Pancake V3 pool.
**Exploitation:** Attacker flash-borrowed 20M USDT, used the proxy exchange() to acquire D3XAT at a low manipulated price, then pumped the PancakeSwap D3XAT/USDT pool with ~6.18M USDT of buys, and sold the proxy-acquired D3XAT back through exchange() at the inflated price, then unwound the Pancake position, netting 190 BNB.
**Escalation:** Multi-round batching (27 Pancake buyers, 2 proxy buyers, 30 sell attempts) to move pool price enough while staying within slippage.
**Insight:** When a protocol's swap/exchange function reads a spot price from an AMM pool, check whether an attacker can pump that same pool in the same transaction and round-trip through the protocol's own exchange() to capture the spread.
