TwentyOne

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

Prediction of "standThreShold" variable

Summary

The dealer's threshold can be manipulated since the randomness is predictible.
The attacker can win all the time, and withdraw all the token of the smart contract.

Vulnerability Details

In traditionnal Black Jack games, threshold is fixed at 17. If the dealer has strictly more than 16 in his hands, he stops here.
Here, the dealer's threshold is calculated before hitting a card.

function call() public {
require(
playersDeck[msg.sender].playersCards.length > 0,
"Game not started"
);
uint256 playerHand = playersHand(msg.sender);
// Calculate the dealer's threshold for stopping (between 17 and 21)
uint256 standThreshold = (uint256(
keccak256(
abi.encodePacked(block.timestamp, msg.sender, block.prevrandao)
)
) % 5) + 17;
// Dealer draws cards until their hand reaches or exceeds the threshold
while (dealersHand(msg.sender) < standThreshold) {
uint256 newCard = drawCard(msg.sender);
addCardForDealer(msg.sender, newCard);
}

The standThreshold variable in TwentyOne:call function, which represents the dealer's threshold, is generated with a pseudorandom mecanism, block.prevrandao.

This implementation causes an issue because this random number is predictible. Since block.prevrandao can be predicted (or manipulated by validators), block.timestamp fixed when the current block is mined,
and msg.sender fixed, the attacker could find the correct configuration to trick this variable.

If the attacker managed to have standThreshold equal to 21, then he will win for sure since the dealer's will always be over 21 (he will hit cards until he reaches 21).

Moreover, the standThreshold variable will remain the same in the same block. If the attacker managed to have multiple transactions in one block, it could win more than one time a block.

Impact

The impact is critical because an attacker could potentially withdaw all the Ether of the smart contract.

Recommended Mitigation

Use Chainlink VRF for true randomness

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.