BriVault inherits OpenZeppelin’s ERC4626 implementation (src/briVault.sol:13) but only overrides the custom deposit. The inherited withdraw/redeem entry points remain callable without the winner lifecycle gates. Once a losing bettor knows the outcome, they can invoke redeem(shares, loser, loser) to reclaim their stake while the vault still expects them to stay locked for payout calculations.
Likelihood: High – ERC4626 redeem is a standard public function that any motivated user or bot can call once the result is known.
Winners recover only their own principal; the prize pool collapses.
Multiple loser exits can drain almost the entire vault before finalization.
Two bettors deposit equal stakes via deposit and join different teams.
Advance time beyond eventEndDate without calling setWinner.
The future loser calls briVault.redeem(briVault.balanceOf(loser), loser, loser).
Owner finalizes with setWinner(winningTeam).
Winning bettor calls withdraw() and receives merely their net stake.
(Reproduced in test/BriVaultAttack.t.sol:75 through testLoserRedeemBreaksPayout.)
Override ERC4626 withdraw and redeem to enforce the same lifecycle and winner checks as the bespoke withdraw(), or disable them entirely.
Snapshot vault assets for payouts only after guarding against ERC4626 exits, or compute fresh balances during withdrawal.
Extend the test suite to cover both standard ERC4626 and custom withdrawal paths.
Proposed patch (Solidity-like pseudocode):
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.