Rock Paper Scissors

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

Player can join token game without any bet

Summary

Player can join token game without any bet.

Vulnerability Details

When player joins an Eth game, there is no validation that the game is an Eth game in function RockPaperScissors::joinGameWithEth:

require(game.state == GameState.Created, "Game not open to join");
require(game.playerA != msg.sender, "Cannot join your own game");
require(block.timestamp <= game.joinDeadline, "Join deadline passed");
require(msg.value == game.bet, "Bet amount must match creator's bet");

The function only has validation that sent Eth value is equal to the game bet amount. Using this function player can join a token game without any bet, because all validations will pass (since game.bet is 0, player just must not send any Eth when calling the function).

Impact

Player can join a token game without any bet and without any risk. having an account with 1 WinningToken, player can mint any amount of tokens by creating a token game, joining to it using function RockPaperScissors::joinGameWithEth and cancelling it.

I created a PoC test that can be added to RockPaperScissorsTest.t.sol:

function testJoinTokenGameWithEth() public {
assertEq(token.balanceOf(playerB), 10);
// First create a game
vm.startPrank(playerA);
token.approve(address(game), 1);
gameId = game.createGameWithToken(TOTAL_TURNS, TIMEOUT);
vm.stopPrank();
// Now join the game
vm.startPrank(playerB);
vm.expectEmit(true, true, false, true);
emit PlayerJoined(gameId, playerB);
game.joinGameWithEth(gameId);
vm.stopPrank();
// Verify game state
(address storedPlayerA, address storedPlayerB,,,,,,,,,,,,,, RockPaperScissors.GameState state) =
game.games(gameId);
assertEq(storedPlayerA, playerA);
assertEq(storedPlayerB, playerB);
assertEq(uint256(state), uint256(RockPaperScissors.GameState.Created));
assertEq(token.balanceOf(playerB), 10);
}

Tools Used

Manual review

Recommendations

Add to the function RockPaperScissors::joinGameWithEth validation that the game is Eth game:

require(game.state == GameState.Created, "Game not open to join");
require(game.playerA != msg.sender, "Cannot join your own game");
require(block.timestamp <= game.joinDeadline, "Join deadline passed");
+require(game.bet > 0, "Cannot join token game");
require(msg.value == game.bet, "Bet amount must match creator's bet");
Updates

Appeal created

m3dython Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Game Staking Inconsistency

joinGameWithEth function lacks a check to verify the game was created with ETH

m3dython Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Game Staking Inconsistency

joinGameWithEth function lacks a check to verify the game was created with ETH

Support

FAQs

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