BriVault

First Flight #52
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: high
Likelihood: medium
Invalid

[H-03] Premature _setWinner Flag Assignment Leads to Inconsistent Finalization State

Root + Impact

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.

Description

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.

//@> _setWinner = true; // ❌ Incorrect: flag set before accounting completes
//@> _getWinnerShares(); // If this reverts, _setWinner remains true (corrupted state)
//@> _setFinallizedVaultBalance(); // Same risk — can revert and leave half-finalized data
emit WinnerSet(winner);
return winner;
}

Risk

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.

Proof of Concept

Recommended Mitigation

-_setWinner = true;
- _getWinnerShares();
- _setFinallizedVaultBalance();
+_getEinnerShares();
+_setFinallizedVaultBalance();
+_setWinner = true;
Updates

Appeal created

bube Lead Judge 19 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!