Winning players can only be paid out when the contract balance is sufficient to pay out an additional 1 ETH on top of the player's deposit. There should be a check in the function TwentyOne::startGame to ensure sufficient funds are availalbe for payout before starting a new game.
The description in the README states that users can wager 1 ETH and that Winning players double their wager, while losing players forfeit their initial bet. This means that winning players should receive 2 ETH when the game ends. Unless a player always looses before a win, the contract needs to be funded with sufficient ETH such that the payout of a win is successful. Thus, if the contract balance is less than 2 ETH when a player wins, the function TwentyOne::endGame will fail and revert, the player won't receive the payout and won't e able to restart a game until the function TwentyOne::endGame is successfully called. A check should be added to the function TwentyOne::startGame to ensure that the contract balance is sufficient to pay out a winning player before starting a new game. Given that multiple players can play the game at the same time, the check should only allow a new game to start if the contract balance is sufficient to pay out all possible winning players.
Player starts game with 1 ETH
Player calls TwentyOne::call
Player wins the game
Function TwentyOne::call calls TwentyOne::endGame to pay out the player
Function TwentyOne::endGame fails and reverts because the contract balance is less than 2 ETH ([OutOfFunds])
No payout for winner, new game can't be started until TwentyOne::endGame is successfully called.
Code:
Place following code into TwentyOne.t.sol:
The function TwentyOne::endGame reverts if there are insufficient funds in the contract to payout the winning player. Thus, players cannot receive payouts for winning a game unless they always loose before a win. In the case the function TwentyOne::endGame fails, the contract will be in a state where no new games can be started until the function TwentyOne::endGame is successfully called. This prevents the same player from playing until the contract is funded with the required amount of ETH or the function TwentyOne::call is repeately called until the player looses. This leads to a poor user experience and may prevent players from continuing to play the game. Due to confusion about not winning, players may also repeately call TwentyOne::call` until the function is successful which in this particular case means they loose the game.
Foundry, manual review
Add a check in the function TwentyOne::startGame to ensure that the contract balance is sufficient to pay out a winning player before starting a new game. The check should only allow a new game to start if the contract balance is sufficient to pay out all possible winning players. This will ensure that players can receive payouts for winning games and that the contract can continue to operate as expected.
Consider to add following code to the TwentyOne::startGame function:
To maintain protocol functionality for multiple cuncurrent players, consider following change in the TwentyOne::initializeDeck and TwentyOne::endGame function:
Change in TwentyOne::initializeDeck:
Change TwentyOne::endGame:
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.