Rock Paper Scissors

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

Reentrancy in RockPaperScissors.joinGameWithToken(uint256)

Summary

The joinGameWithToken() function performs an external call to a user-supplied token contract (transferFrom) before updating internal contract state. This opens the door for a reentrancy attack, where a malicious token contract could call back into the same or related function before the state is finalized, potentially causing logic corruption or unauthorized access.

Vulnerability Details

Function:

function joinGameWithToken(uint256 _gameId) external

winningToken.transferFrom(msg.sender, address(this), 1);
game.playerB = msg.sender;

The external call to transferFrom() is made before updating the game state (game.playerB = msg.sender). If the token is a malicious ERC-20 implementation, it could exploit the callback inside transferFrom() to re-enter the same function or related logic. Since the state has not been updated yet, the contract could process the same request multiple times, leading to state inconsistency or duplicate joins.

Impact

  • State corruption: game.playerB might be set multiple times or bypass game logic entirely.

  • Potential game logic abuse: Attackers could join multiple games or manipulate roles in active sessions.

  • Reentrancy attack vector: A malicious token can exploit the callback mechanism in transferFrom() to reenter the contract.

Tools Used

Manual review

Recommendations

Move state update before any external calls

game.playerB = msg.sender;
require(winningToken.transferFrom(msg.sender, address(this), 1), "Token transfer failed");
Updates

Appeal created

m3dython Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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