Rock Paper Scissors

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

Joined Games Can Be Overwritten by Recalling joinGame with Existing Game ID

Description

The joinGameWithEth and joinGameWithToken functions allow a user to join a game if the game.state is GameState.Created. However, the game.state is never updated to GameState.Joined` or similar after playerB joins. As a result, anyone can re-call the joinGame function on an already joined game and overwrite playerB with a new address, as long as the join conditions still pass.

Proof of Concept

// Alice creates game with ID 1

rockPaperScissors.createGameWithEth{value: 1 ether}(...);

// Bob joins game ID 1

rockPaperScissors.joinGameWithEth{value: 1 ether}(1);
```
// Charlie joins the same game ID 1
```solidity
rockPaperScissors.joinGameWithEth{value: 1 ether}(1);

// Now Charlie is playerB, overwriting Bob's original slot

Impact

  • PlayerB can be overwritten after the game is already joined.

  • A malicious actor could front-run legitimate joiners to hijack games.

  • Original playerB may have already sent funds or transferred tokens.

This can lead to funds being misassigned, griefing, and broken trust in the match system.

Recommendation

Update the game state once playerB joins. For example:

require(game.playerB == address(0), "Game already joined");
game.playerB = msg.sender;
game.state = GameState.Joined; // optional, for clarity

This prevents subsequent joins after a game is filled.

Tools used manual review

Updates

Appeal created

m3dython Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Absence of State Change on Join Allows Player B Hijacking

Game state remains Created after a player joins

Support

FAQs

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