# State Transition: Minipools can be created using other operator's AVAX deposit via recreateMinipool

recreateMinipool on a Finished minipool re-enters Prelaunch without re-collecting the operator's AVAX, letting it launch on another operator's vault deposit and blocking that pool.

- Payout: Contest reward
- Severity: medium
- Program: GoGoPool
- Credited: hansfriese
- Disclosed: 2023-03-21
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-12-gogopool-findings/issues/569
- Library page: https://bugbountylibrary.com/r/c4%3A2022-12-gogopool%3AM-09
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:chained technique:source-review vuln:accounting-error vuln:business-logic

**Target:** MinipoolManager state machine / vault accounting
**Root cause:** recreateMinipool allows transitions from Withdrawable/Finished/Error/Canceled to Prelaunch, but these states differ in whether the node operator's AVAX is still in the vault; the vault balance is not tracked per staker, so a Finished pool (funds already withdrawn) can be recreated and launched using AVAX deposited by other Prelaunch minipools.
**Steps:**
1. Node Op1 creates minipool mp1 (deposit 1000 AVAX + 1000 assignment); Node Op2 creates mp2 similarly.
2. Rialto drives mp1 Prelaunch->Launched->Staking, then recordStakingError (Staking->Error) with validationAmt.
3. Node Op1 calls withdrawMinipoolFunds -> mp1 Finished, AVAX returned to operator.
4. Rialto calls recreateMinipool(mp1) -> mp1 back to Prelaunch with no operator deposit; vault still holds mp2's deposit.
5. Rialto drives mp1 Prelaunch->Launched->Staking; mp1 now staked using mp2's AVAX.
6. claimAndInitiateStaking(mp2) reverts with Vault.InsufficientContractBalance.
**How found:** Manual review of the minipool state machine diagram: noticed the four states feeding recreateMinipool are not equivalent in whether the operator's AVAX remains in the vault, then wrote a Foundry test to confirm the vault balance is drained by the recreated pool.
**Exploitation:** Requires Rialto (oracle) to call recreateMinipool on a Finished pool; Franfran noted it can be forced by frontrunning the Rialto transaction. Attacker's pool then launches on another operator's vault deposit, and the victim pool cannot launch.
**Escalation:** Frontrunning Rialto to force the recreate on a Finished pool (per Franfran's #484) rather than relying on operator error.
**Insight:** When auditing FSMs, enumerate every state that can transition into a shared 'reset' function and check whether each source state leaves the contract's balance/accounting in the same shape; shared vaults without per-staker accounting let a reset pool consume funds deposited for other pending entries.
