# ERC20TokenBank: Curve price manipulation drains $111k via doExchange

ERC20TokenBank's doExchange used manipulable Curve pool price, letting attacker flash-loan USDC, skew pool, and drain ~$111k.

- Payout: Real-world hack
- Severity: high
- Program: ERC20TokenBank
- Analysis by: DeFiHackLabs
- Disclosed: 2023-05-31
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-05/ERC20TokenBank_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20230531-erc20tokenbank
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity vuln:flash-loan vuln:oracle-manipulation

**Target:** ERC20TokenBank doExchange contract on Ethereum
**Root cause:** doExchange relied on the spot price from a Curve Y pool (exchange_underlying) without any TWAP or slippage protection, so a large swap could arbitrarily skew the exchange rate used.
**Steps:**
1. Flash-loan 120,000 USDC from Uniswap V3 pair `0x5777d92f208679DB4b9778590Fa3CAB3aC9e2168`.
2. In the flash callback, call `curveYSwap.exchange_underlying(1, 2, 120_000 * 1e6, 0)` to swap USDC into USDT, skewing the Curve pool price.
3. Call `ExchangeBetweenPools.doExchange(victimAmount)` where victimAmount = `119_023_523_157`, exploiting the manipulated price.
4. Swap back via `curveYSwap.exchange_underlying(2, 1, USDT.balanceOf(address(this)), 0)`.
5. Repay the flash loan: `USDC.transfer(address(Pair), 120_000 * 1e6 + uint256(amount1))`.
**Exploitation:** Attacker flash-borrowed 120k USDC, dumped it into Curve Y pool to crash USDC price / inflate USDT, then called the vulnerable doExchange which priced assets off that skewed pool, extracting value, then reversed the swap and repaid the flash loan, keeping ~$111k profit.
**Insight:** Contracts that call Curve's exchange_underlying for pricing are vulnerable to single-block spot manipulation; check whether the victim contract reads pool reserves directly and whether a flash loan can move them enough to profit.

