Rock Paper Scissors

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

Infinite Minting Vulnerability in Token-Based Rock Paper Scissors Games via Unrestricted Minting Rendering The Token Worthless

Summary

The contract mints new WinningToken tokens during game resolution (completion/cancellation) instead of transferring the originally staked tokens locked in the contract. This creates an infinite supply of tokens and permanently traps user-deposited tokens in the contract.

Vulnerability Details

Affected Components

  1. **Token Prize Distribution **

    (`RockPaperScissors::_finishGame` function)

  2. Game Cancellation Logic (RockPaperScissors::_cancelGame function)

Key Vulnerable Code Snippets

1. Faulty Minting in Game Completion (RockPaperScissors::_finishGame):

function _finishGame(...) internal {
if (game.bet == 0) { // Token-based game
winningToken.mint(_winner, 2); // Mints new tokens
}
}

2. Faulty Minting in Game Cancellation (RockPaperScissors::_cancelGame):

function _cancelGame(...) internal {
if (game.bet == 0) { // Token-based game
winningToken.mint(game.playerA, 1); // Mints new tokens
winningToken.mint(game.playerB, 1);
}
}

Attack Scenarios & Impact

Scenario 1: Infinite Token Minting via Game Cancellation

  1. Step 1: Attacker creates a token-based game (transfers 1 WinningToken to the contract).

  2. Step 2: Attacker joins their own game with a second account (transfers another token).

  3. Step 3: Attacker cancels the game via timeoutJoin.

  4. Result:

    • Contract mints 2 new tokens (1 to each "player").

    • Original 2 tokens remain locked in the contract.

    • Total token supply increases by +2 per iteration.

Scenario 2: Infinite Token Minting via Game Completion

  1. Step 1: Attacker creates a single-turn token game.

  2. Step 2: Attacker completes the game (winning fairly or via timeout).

  3. Result:

    • Contract mints 2 new tokens to the winner.

    • Original 2 tokens remain locked in the contract.

    • Total token supply increases by +2 per game.

Impact

  • Token Supply: Infinite inflation via unrestricted minting, rendering the token worthless.

  • User Funds: All tokens deposited in games are permanently locked in the contract.

  • Protocol Integrity: Loss of trust due to broken economic model and inability to honor token redemptions.

Tools Used

Recommendations

  1. Replace Minting with Token Transfers:

// In _finishGame
if (game.bet == 0) {
winningToken.transfer(_winner, 2); // Transfer locked tokens
}
// In _cancelGame
if (game.bet == 0) {
winningToken.transfer(game.playerA, 1); // Return original tokens
if (game.playerB != address(0)) {
winningToken.transfer(game.playerB, 1);
}
}
  1. Add Balance Checks:

// Ensure contract has sufficient tokens before transferring
require(winningToken.balanceOf(address(this)) >= 2, "Insufficient tokens");
  1. Burn Tokens on ETH Game Wins:

// In ETH-based _finishGame
winningToken.burn(address(this), 1); // Destroy token after ETH game
Updates

Appeal created

m3dython Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

Minting Instead of Transferring Staked Tokens

Mints new tokens upon game completion or cancellation for token-based games

Support

FAQs

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