# Poolz LockedDeal: integer overflow in CreateMassPools drains pools

Poolz LockedDeal CreateMassPools integer overflow let attacker mint a huge pool balance then WithdrawToken drained ~$390K across MNZ, SIP, WOD, ECIO.

- Payout: Real-world hack
- Severity: high
- Program: - Poolz
- Analysis by: DeFiHackLabs
- Disclosed: 2023-03-15
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-03/poolz_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20230315-poolz
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity vuln:accounting-error vuln:business-logic

**Target:** LockedDeal vesting/pool contract on BSC
**Root cause:** CreateMassPools sums user-supplied transfer amounts without overflow protection; passing `type(uint256).max - poolBalance + 2` wraps the accounting so the created pool's balance exceeds reality, and WithdrawToken pays out the inflated amount.
**Steps:**
1. Flash loan 1e18 WBNB from DPPAdvanced.
2. Withdraw WBNB, swap to target token (e.g. MNZ) via PancakeRouter.
3. Approve token to LockedDeal and router.
4. Read `mnz_balance = mnz.balanceOf(poolzpool)`.
5. Set `overflow_data = type(uint256).max - mnz_balance + 2`.
6. Call `poolzpool.CreateMassPools(address(mnz), begintime, [overflow_data, mnz_balance], [this, this])`.
7. Call `poolzpool.WithdrawToken(lastPoolId)` to receive inflated token amount.
8. Swap tokens back to WBNB via PancakeRouter; repeat for SIP, WOD, ECIO.
9. Repay 1e18 WBNB flash loan.
**Exploitation:** Attacker flash-borrowed WBNB, bought each victim token, then abused CreateMassPools overflow to create a pool whose recorded balance wrapped around, immediately withdrew the inflated amount via WithdrawToken, sold tokens on PancakeSwap for WBNB, and repeated across four tokens before repaying the flash loan.
**Escalation:** Same overflow primitive reused sequentially against MNZ, SIP, WOD, and ECIO pools to multiply drained value.
**Insight:** When a contract sums user-supplied amounts into a pool balance, check whether the sum can wrap; a value of `max - currentBalance + 2` makes the recorded balance exceed the real deposit, and any immediate withdraw function turns that into free tokens.

