TwentyOne

First Flight #29
Beginner FriendlyGameFiFoundrySolidity
100 EXP
View results
Submission Details
Severity: low
Invalid

Predictable randomness mechanism exposes contract to front-running attacks, compromising game iIntegrity

Summary

The TwentyOne contract's randomness mechanism relies on block.timestamp and block.prevrandao, which are predictable values. This enables malicious players to front-run transactions by calculating cards and outcomes in advance, giving them an unfair advantage in the game. The vulnerability affects multiple key functions including startGame(), hit(), and call(), potentially compromising the entire game's integrity.

Vulnerability Details

Vulnerability stems from using predictable blockchain parameters for randomness:

uint256 randomIndex = uint256(keccak256(
abi.encodePacked(block.timestamp, msg.sender, block.prevrandao)
)) % availableCards[player].length;```

This affects three main functions:

  • startGame() function:

function startGame() public payable returns (uint256) {
address player = msg.sender;
require(msg.value >= 1 ether, "not enough ether sent");
initializeDeck(player);
uint256 card1 = drawCard(player); // Vulnerable to prediction
uint256 card2 = drawCard(player); // Vulnerable to prediction
// ... rest of function
}```
  • hit() function:

function hit() public {
// ... checks ...
uint256 newCard = drawCard(msg.sender); // Vulnerable to prediction
addCardForPlayer(msg.sender, newCard);
// ... rest of function
}```
  • call() function:

function call() public {
// ... previous code ...
uint256 standThreshold = (uint256(keccak256(...)) % 5) + 17; // Vulnerable to prediction
while (dealersHand(msg.sender) < standThreshold) {
uint256 newCard = drawCard(msg.sender); // Vulnerable to prediction
addCardForDealer(msg.sender, newCard);
}
// ... determine winner ...
}```

Scenario of the attack can be as follows:
Attacker monitors the mempool for pending game transactions. For each transaction, attacker can:

  • Calculate the exact cards that will be drawn using the same inputs

  • Determine if the outcome will be favorable

  • Front-run the transaction with their own if favorable

  • Wait for next block if unfavorable

Impact

Attackers can exploit it to predict the cards and outcomes, and subsequently front-run transactions to secure favorable outcomes for themselves. This undermines the integrity of the game, leading to unfair advantages and potential financial loss for other players.

Tools Used

  • Manual Code Review

  • Foundry

Recommendations

Use an off-chain randomness source provided by trusted third parties, such as Chainlink’s VRF oracles, that ensure fairness and randomness. This prevents the exploitation of blockchain parameters, and improves security by moving the randomness process off-chain.

Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

[INVALID] Known - Randomness

Randomness Manipulation: The randomness mechanism relies on block.timestamp, msg.sender, and block.prevrandao, which may be predictable in certain scenarios. Consider using Chainlink VRF or another oracle for more secure randomness.

Support

FAQs

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