The joinGameWithToken
function fails to transition the game state after a player successfully joins as playerB
. This oversight allows subsequent calls to the same function (before the game moves to the commit phase) to replace the initially joined playerB
, specifically in games designed to use the WinningToken
.
The intended flow for a token game involves:
Player A creates a game using createGameWithToken
. The game state is Created
.
Player B approves the RockPaperScissors
contract to spend their WinningToken
.
Player B calls joinGameWithToken
. The function verifies conditions, including game.state == GameState.Created
, transfers the token via transferFrom
, and sets game.playerB
.
The vulnerability lies in the fact that after step 3, the game.state
remains GameState.Created
.
Consider this scenario:
Alice creates a token game (ID: 101). games[101].state
is Created
.
Bob approves the contract and calls joinGameWithToken(101)
. The token is transferred, and games[101].playerB
becomes Bob's address. Crucially, games[101].state
is still Created
.
Before Alice or Bob calls commitMove
, Charlie (who has also approved the contract) calls joinGameWithToken(101)
.
Charlie's call finds games[101].state
is still Created
, passes all checks, transfers his token, and overwrites games[101].playerB
to Charlie's address.
The commitMove
function is the first place the state would change to Committed
, but this happens too late to prevent the overwrite during the joining phase.
This vulnerability allows the second player (playerB
) slot in token games to be usurped before the game properly starts. The first user (Bob in the example) successfully joins, has their token taken by the contract, but is then silently replaced by a subsequent joiner (Charlie). This leads to:
Game Disruption: The intended player B cannot participate.
Potential Griefing: Malicious actors can specifically target players trying to join games by quickly joining after them.
Locked Tokens : Bob's token is held by the contract leading to loss of funds.
Manual code review.
The vulnerability is resolved by ensuring the game state transitions immediately upon a successful join, preventing further joins. Add a state change within joinGameWithToken
right after playerB
is set.
Game state remains Created after a player joins
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.