The TwentyOne contract fails to implement proper balance checks before processing payouts. Since each win pays out 2 ETH but each game only requires 1 ETH to play, the contract will eventually become insolvent and unable to pay winners, regardless of whether the wins are concurrent or sequential.
Location: src/TwentyOne.sol
The vulnerability exists in the fundamental economics of the game:
Players bet 1 ETH to play
Winners receive 2 ETH payout
No balance checks before payouts
No house funding mechanism
Proof of Concept:
The vulnerability has several severe implications:
Guaranteed Insolvency
Each winning player reduces contract balance by 1 ETH (receives 2 ETH, paid 1 ETH)
Contract will eventually run out of funds with enough wins
No mechanism to replenish contract funds
Game Fairness
Winners may not receive their legitimate winnings
Players could lose their bets without any chance of receiving winnings
Game becomes unplayable once contract is drained
Economic Design Flaw
House edge is negative (-100%) as players bet 1 ETH to win 2 ETH
No sustainable economic model for contract operation
Contract requires constant external funding to remain solvent
Foundry Testing Framework
Manual Code Review
Custom test cases for concurrent winning scenarios
Implement Balance Checks:
Implement Game State Management:
Track total potential payouts based on active games
Prevent new games from starting if insufficient funds for potential payouts
Consider implementing a reserve requirement
Add Circuit Breaker:
Consider Alternative Payout Models:
Implement a queue-based payout system
Add partial payout capabilities
Consider implementing a maximum concurrent player limit
Improve Monitoring:
Add events for failed payouts
Track and monitor contract balance
Implement automatic top-up mechanisms when balance is low
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.