A logical vulnerability exists in the RockPaperScissors
smart contract, specifically in the joinGameWithEth
function. The contract fails to validate whether the game being joined is an ETH-based game or a token-based game, leading to a critical inconsistency. This allows malicious players to join token-based games using 0 ETH, bypassing the required entry conditions.
The vulnerability lies in the lack of a check within the joinGameWithEth
function to confirm that the game being joined was originally created as an ETH-bet game. This function assumes all games it handles require ETH, but the contract supports a parallel system where games can be created using WinningToken
instead of ETH.
There is no validation ensuring game.bet > 0
, which means a malicious actor can:
Locate or monitor for games created via createGameWithToken
, where game.bet == 0
.
Call joinGameWithEth(_gameId)
and send msg.value == 0
.
Successfully join a token-based game without holding or transferring the required WinningToken
.
This undermines the economic model and fairness of the contract.
This vulnerability enables:
Unauthorized participation in token-based games without fulfilling the token requirement.
Economic exploitation, where users bypass the token staking mechanism entirely, disrupting the designed incentive model.
Game state corruption, potentially causing inconsistencies in logic flow and unexpected behavior in later game phases (e.g., prize distribution or score tracking).
Loss of trust, as honest players who participate according to the rules may end up competing against players who didn’t meet the same entry criteria.
This is a critical severity issue due to the potential for misuse and the violation of the core rules of game entry.
Manual source code review
Static analysis (via IDE/VSCode/Hardhat plugin)
Logical reasoning (no formal tools needed in this specific case)
Add a condition in joinGameWithEth
to ensure the target game was created with ETH as the betting mechanism. Specifically:
This should be inserted before any assignment or state change. Additionally, you may consider:
Introducing a boolean flag (e.g., isEthGame
) to the Game
struct to make type-checking more explicit and efficient.
Applying the same principle to joinGameWithToken
to ensure symmetry and robustness.
Adding tests to cover edge cases where ETH-based and token-based logic might be misused or intersect unexpectedly.
joinGameWithEth function lacks a check to verify the game was created with ETH
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.