Rock Paper Scissors

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

Unchecked Game Cancellation Allows Unlimited Token Minting (Improper Token Handling + Supply Inflation)

Summary

The current implementation of the RockPaperScissors::_cancelGame function allows a user to create a game with a token bet and immediately cancel it while the game is still in the "Created" state. If no one has joined or if neither player has committed, the user can call the cancellation function to receive minted tokens instead of returning the originally sent tokens.

This behavior leads to the minting of new tokens instead of transferring the existing ones back to the creator, enabling attackers to exploit this mechanism. By repeatedly creating and canceling games, an attacker can mint an unlimited number of tokens, resulting in token supply inflation. This vulnerability arises due to improper tracking of tokens sent to the contract and the failure to return or burn those tokens upon cancellation.

Vulnerability Details

Initial Setup:

  • Player1 has 10 tokens, contract has 0.

Game Creation:

  • Player1 creates a game, spending 1 token.

  • New balances: Player1: 9 tokens, Contract: 1 token.

Game Cancellation:

  • Player1 cancels the game.

  • Final balances: Player1: 10 tokens (refund received), Contract: 1 token.

Conclusion:

  • The test confirms that after game cancellation, the player gets their token back, but the contract retains 1 token.

function testCancelGameTokenInflation() public {
// Player1 creates a game with a token bet
uint256 initialPlayer1Balance = token.balanceOf(playerA);
uint256 initialContractBalance = token.balanceOf(address(game));
console.log("Initial player1 balance: ", initialPlayer1Balance);
console.log("Initial contract balance: ", initialContractBalance);
vm.startPrank(playerA);
// Approve token transfer
token.approve(address(game), 1);
// Player1 creates a game
gameId = game.createGameWithToken(5, 5 minutes);
vm.stopPrank();
// Simulate player1 immediately canceling the game
vm.prank(playerA);
game.cancelGame(gameId);
// Verify player1 gets their token back
uint256 player1NewBalance = token.balanceOf(playerA);
assertEq(
player1NewBalance,
initialPlayer1Balance,
"Player1 should get their 1 token back after cancellation"
);
console.log("New player1 balance: ", player1NewBalance);
// Check the contract balance - it should not have increased by 1 (indicating minting occurred)
uint256 contractNewBalance = token.balanceOf(address(game));
assertEq(
contractNewBalance,
initialContractBalance + 1,
"Contract balance should remain the same after cancellation"
);
console.log("New contract balance: ", contractNewBalance);
}

Impact

The impact of this vulnerability is significant as it allows an attacker to artificially inflate the token supply by repeatedly creating and canceling games. Since tokens are minted for the creator instead of returning the original bet, the attacker can amass an arbitrary number of tokens without any real stake in the game.

This inflation of tokens undermines the token economy, potentially decreasing the value of the token, destabilizing its market price, and eroding trust in the system. Furthermore, the lack of proper token tracking and handling can lead to a loss of integrity in the game's mechanics and economy, potentially causing long-term damage to the project's reputation and financial stability.

Tools Used

  • Foundry

Recommendations

Replace the logic that mints new tokens upon game cancellation with a mechanism that instead either:

  1. Transfers the originally staked tokens back to the player from the contract’s balance, or

  2. Burns the tokens held by the contract and mint fresh tokens to the players, that way the tokenomics stays in check.

Updates

Appeal created

m3dython Lead Judge 4 months 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

m3dython Lead Judge 4 months 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.