Player can force win by blocking opponent's turn exploiting lack of reveal deadline reset
The function RockPaperScissors::_determineWinner() implements the complex logic covering turn winner determination, reset after each turn and game completion along with distribution of rewards/refunding. After turn winner determination in the top of the implementaiton, following is the game settings reset, preparing for the next turn. Current turn is incremented, player commits are put in initial state, along with the revealed moves. At the end game state is moved back to GameState.Committed. Missing is only revealDeadline reset, which could cause the entire game to be blocked further and one of the players to force win. If the players complete quickly the current turn before revealDeadline expiration, when the next turn starts, each player is able to block the other one from commiting its hashed value. The fragile validation of function RockPaperScissors::revealMove() could be exploited from anyone of the players by sequentially committing the hashed value and further revealing the move. All the checks will be passed in case the revealDeadline still not expired. When the opponent tries later to commit hashed move, the function RockPaperScissors::commitMove() will revert with Moves already committed for this turn blocking the player.
Function RockPaperScissors::_determineWinner():
Function RockPaperScissors::revealMove()
Function RockPaperScissors::commitMove()
Мissing reset of revealDeadline along with other game stats at the end of the turn:
unlocks RockPaperScissors::revealMove for a window until revealDeadline is expired
each of the players can do a commit, followed sequentially by reveal (no need to wait for opponent to commit in order revealTimeout is set and revealing be enabled)
lets assume playerA has done a sequential commit + reveal
further attempts of opponent (playerB) to make a commit will fail
playerA could wait util revealDeadline expired and call funciton RockPaperScissors::timeoutReveal() in order to force the win and collect the entire reward
Manual review
Foundry
Add the following test to RockPaperScissors.t.sol.
Reset revealDeadline at the end of the turn in function RockPaperScissors::_determineWinner()
Protocol does not provide a way for Player B to exit a game and reclaim their stake if Player A stops participating
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.