Rock Paper Scissors

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

Unrestricted Game Cancellation After Player Joins

Summary

The RockPaperScissors contract allows the game creator to cancel a game after the second player has joined but before any moves are committed. This creates an unfair advantage where the creator can selectively choose opponents by cancelling games when undesired players join.

Vulnerability Details

The cancelGame function allows the creator to cancel a game as long as it's in the Created state:

function cancelGame(uint256 _gameId) external {
Game storage game = games[_gameId];
require(game.state == GameState.Created, "Game must be in created state");
require(msg.sender == game.playerA, "Only creator can cancel");
_cancelGame(_gameId);
}

After Player B joins via joinGameWithEth or joinGameWithToken, the game remains in the Created state until moves are committed. This allows Player A to see who joined their game and cancel if they prefer not to play against that specific opponent.

Impact

This vulnerability allows:

  1. Selective Play: Game creators can cherry-pick opponents by cancelling games when undesired players join

  2. Griefing: Creators can waste other players' time and gas by repeatedly creating and cancelling games

While players do get their ETH or tokens refunded when a game is cancelled, they waste gas fees and time attempting to join games that get cancelled.

Tools Used

Manual code review

Recommendations

Prevent cancellation after a player has joined by adding a check for Player B:

function cancelGame(uint256 _gameId) external {
Game storage game = games[_gameId];
require(game.state == GameState.Created, "Game must be in created state");
require(msg.sender == game.playerA, "Only creator can cancel");
require(game.playerB == address(0), "Cannot cancel after player has joined"); // << --
_cancelGame(_gameId);
}

This ensures games can only be cancelled before an opponent joins, ensuring fair play and preventing selective opponent choice.

Updates

Appeal created

m3dython Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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