Root Cause:
The contract sets _setWinner = true before executing and confirming the success of the critical accounting functions _getWinnerShares() and _setFinallizedVaultBalance().
If either of these internal calls reverts or fails part-way, the flag remains permanently true, leaving the contract in an inconsistent “finalized” state with incomplete or zeroed accounting values.
Impact:
Once the protocol believes finalization is complete, subsequent calls to withdraw() and other winnerSet-guarded functions operate on corrupted data.
This results in incorrect payout calculations, potential fund loss, or a full protocol freeze, since there is no way to revert the flag or recompute the correct totals.
Normal Behavior:
When the event ends, the contract owner should call setWinner() to finalize results. This process should first calculate all winner-related accounting values — such as total winning shares and final vault balance — and only after these are successfully computed should the _setWinner flag be updated to true. This ensures all subsequent functions operate on a consistent and verified state.
Issue:
In the current implementation, _setWinner is assigned true before the accounting logic executes. If _getWinnerShares() or _setFinallizedVaultBalance() reverts, runs out of gas, or fails to complete, the flag remains permanently true even though no valid winner data or final balances are recorded. This breaks the finalization invariant, allowing withdrawals or state transitions to occur based on incomplete data, which can corrupt the entire payout process or freeze funds.
Likelihood:
Every call to setWinner() triggers _setWinner = true before executing critical accounting (_getWinnerShares() and _setFinallizedVaultBalance()), so this inconsistent state can occur during any normal finalization attempt.
Any revert or out-of-gas error inside those internal calls leaves _setWinner permanently true, making the condition reproducible whenever gas limits or invalid data are present.
Impact:
The contract can mark itself as finalized even though accounting is incomplete, causing inaccurate payout calculations or permanent protocol freeze.
Subsequent functions guarded by winnerSet (like withdraw) operate on corrupted state, leading to incorrect fund distribution or denial of withdrawals.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.