<!-- canonical: https://0xsimao.com/findings/blast-ido-pools-withdraw-spare-several-rounds -->

# `IDOPoolAbstract::withdrawSpareIDO()` does not take into account that several rounds may use the same `IdoToken`

Medium · Three Sigma · IDO launchpad · 7th August, 2024

Finding M-1 of the Blast IDO Pools security review.

- Protocol: https://docs.blastup.io/blastup-docs
- Report: /reports/blast-ido-pools
- Source: https://cdn.sanity.io/files/qoqld077/production/d2a7ca81740e715b604122c12dafbce599e43f2f.pdf

---

### Description

`IDOPoolAbstract::withdrawSpareIDO()` checks if `contractBal >= ido.idoSize`, where `contractBal = IERC20(ido.idoToken).balanceOf(address(this))`. When several rounds use the same `ido.idoToken`, this check is incomplete as `ido.idoSize` only tracks the tokens of one round.

### Recommendation

The correct check is withdrawing `contractBal - globalTokenAllocPerIDORound[idoConfig.idoToken]`, correctly tracking excess tokens.

---

Related findings:

- [DoSed liquidations as `PrizeVault::liquidatableBalanceOf()` does not take into account the `mintLimit` when the token out is the asset](https://0xsimao.com/findings/pooltogether-the-prize-layer-for-defi-liquidations-prize-liquidatable-mint): PoolTogether Prize Layer
- [Users cannot unstake from YiedlETHStakingEtherfi.sol, because YieldAccount.sol is incompatible with ether.fi's WithdrawRequestNFT.sol](https://0xsimao.com/findings/benddao-unstake-eth-staking-yield): BendDAO
- [Balance check in Vault::withdraw() does not take fees into account](https://0xsimao.com/findings/orange-balance-withdraw-fees-account): Orange Bridge
- [ERC4626YieldBackend.withdrawSurplus() uses convertToAssets() which doesn't account for fees](https://0xsimao.com/findings/superfluid-erc4626-yield-withdraw-fees): Superfluid Yield Backends
