Rock Paper Scissors

First Flight #38
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Invalid

Missing else block in _cancelGame() __RockPaperScis

Summary

The _cancelGame function is missing else block to handle unexpected game.bet values.

Vulnerability Details

The function currently handles two cases:

If game.bet > 0: refund ETH to players

If game.bet == 0: gives tokens to the players

However, if game.bet is set to an unexpected or invalid non-zero value (e.g., due to a bug), neither condition is met, and the game is still marked as cancelled.

This results in:

No ETH refund

No tokens minting

No error or revert

function _cancelGame(uint256 _gameId) internal {
Game storage game = games[_gameId];
game.state = GameState.Cancelled;
// Refund ETH to players
if (game.bet > 0) {
(bool successA,) = game.playerA.call{value: game.bet}("");
require(successA, "Transfer to player A failed");
if (game.playerB != address(0)) {
(bool successB,) = game.playerB.call{value: game.bet}("");
require(successB, "Transfer to player B failed");
}
}
// Return tokens for token games
if (game.bet == 0) {
if (game.playerA != address(0)) {
winningToken.mint(game.playerA, 1);
}
if (game.playerB != address(0)) {
winningToken.mint(game.playerB, 1);
}
}
emit GameCancelled(_gameId);
}

Impact

Funds loss

Players might not get ETH or tokens

Tools Used

Manual review

Recommendations

Add an else block to explicitly handle invalid or unexpected game.bet values.

Fixed code

function _cancelGame(uint256 _gameId) internal {
Game storage game = games[_gameId];
game.state = GameState.Cancelled;
// Refund ETH to players
if (game.bet > 0) {
(bool successA,) = game.playerA.call{value: game.bet}("");
require(successA, "Transfer to player A failed");
if (game.playerB != address(0)) {
(bool successB,) = game.playerB.call{value: game.bet}("");
require(successB, "Transfer to player B failed");
}
}
// Return tokens for token games
if (game.bet == 0) {
if (game.playerA != address(0)) {
winningToken.mint(game.playerA, 1);
}
if (game.playerB != address(0)) {
winningToken.mint(game.playerB, 1);
}
} else {
revert("Invalid game state");
}
emit GameCancelled(_gameId);
}
Updates

Appeal created

m3dython Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational

Code suggestions or observations that do not pose a direct security risk.

m3dython Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational

Code suggestions or observations that do not pose a direct security risk.

Support

FAQs

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