Rock Paper Scissors

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

Missing Token Allowance Check in Token-Based Game Creation/Joining

Summary

The createGameWithToken and joinGameWithToken functions lack explicit checks for token allowances before transferring players' RPSW tokens to the contract. This oversight may cause transactions to revert unexpectedly if users have not properly approved the contract to spend their tokens, leading to a poor user experience and potential confusion.

Vulnerability Details

Affected Functions:

  1. createGameWithToken

    • Purpose: Allows players to create a game using RPSW tokens instead of ETH.

    • Issue: Calls transferFrom without verifying allowance for the contract.

  2. joinGameWithToken

    • Purpose: Allows players to join a token-based game.

    • Issue: Similar missing allowance check before transferFrom.

Technical Context:

ERC20 tokens require explicit approval via approve or increaseAllowance before a contract can transfer tokens on behalf of a user. While transferFrom inherently checks the allowance, failing to include explicit require statements for allowance validation results in opaque transaction reverts with generic errors (e.g., "ERC20: insufficient allowance"). This makes debugging difficult for end-users.

Impact

  • User Experience Degradation: Transactions may fail silently without clear error messages, confusing users.

  • Potential Frontend Misalignment: If frontends assume allowance checks are handled by the contract, improper error handling could lead to UI inconsistencies.

  • No Direct Fund Loss: The bug does not risk fund loss but disrupts protocol usability.

Tools Used

  • Manual code review

  • Foundry/Forge

Code Fix:

Add explicit require statements to validate token allowances before calling transferFrom in both functions.

Modified createGameWithToken Function:

function createGameWithToken(uint256 _totalTurns, uint256 _timeoutInterval) external returns (uint256) {
// Add allowance check
require(
winningToken.allowance(msg.sender, address(this)) >= 1,
"Insufficient token allowance"
);
require(winningToken.balanceOf(msg.sender) >= 1, "Must have winning token");
require(_totalTurns > 0, "Must have at least one turn");
require(_totalTurns % 2 == 1, "Total turns must be odd");
require(_timeoutInterval >= 5 minutes, "Timeout must be at least 5 minutes");
// Transfer token to contract
winningToken.transferFrom(msg.sender, address(this), 1);
// ... rest of the function unchanged ...
}

Modified joinGameWithToken Function:

function joinGameWithToken(uint256 _gameId) external {
Game storage game = games[_gameId];
// Add allowance check
require(
winningToken.allowance(msg.sender, address(this)) >= 1,
"Insufficient token allowance"
);
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, "This game requires ETH bet");
require(winningToken.balanceOf(msg.sender) >= 1, "Must have winning token");
// Transfer token to contract
winningToken.transferFrom(msg.sender, address(this), 1);
// ... rest of the function unchanged ...
}

Key Modifications:

  • Added require(winningToken.allowance(...)) checks (highlighted) to explicitly validate token allowances.

  • Error messages now clearly indicate insufficient allowance issues.

Additional Recommendations:

  • Frontend Guidance: Ensure frontend applications prompt users to approve token allowances before initiating transactions.

  • Event Logging: Emit events after successful approvals to assist in tracking user interactions.

Updates

Appeal created

m3dython Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Broken Token Game Creation

createGameWithToken and joinGameWithToken functions will revert because they attempt transferFrom without requiring the user to first approve

Support

FAQs

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