The drawCard()
function in the TwentyOne
smart contract uses a weak pseudorandom number generator (PRNG) to select a card for the player. This randomness is derived from a combination of block.timestamp
, msg.sender
, and block.prevrandao
. Due to the predictability and potential manipulability of these inputs, the randomness used to determine the card drawn can be predicted or influenced by an attacker, undermining the fairness of the game.
The card drawn for a player is determined using the following line of code:
The randomness is generated from the concatenation of block.timestamp
, msg.sender
, and block.prevrandao
.
block.timestamp
can be slightly adjusted by miners within a certain range, introducing predictability.
msg.sender
is the player's address, which is always known and predictable.
block.prevrandao
is a hash of the previous block’s random value, which while harder to influence, can still be manipulated by miners in certain circumstances.
This weak randomness makes it possible for an attacker to predict or influence the card drawn, especially by timing their transactions in specific ways or analyzing patterns in previous draws.
The impact of this vulnerability is moderate to high, depending on the attacker’s ability to control or predict the randomness. If an attacker can predict the card being drawn, they could adjust their strategy in ways that would lead to favorable outcomes.
For example, if a player can predict the card they will receive, they might decide to hit or stand with knowledge of the upcoming card, which could allow them to win unfairly.
Furthermore, an attacker could manipulate the randomness by interacting with the contract at precise times when they know the random values are more likely to produce favorable outcomes.
While this randomness affects only the individual card draw, in a game of chance, even minor manipulation can lead to significant advantage and degrade the fairness of the game.
Slither
Use Chainlink VRF to handle random number generation.
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.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.