The EggHuntGame
contract uses a flawed pseudo-random number generator (PRNG) in the searchForEgg
function, which relies on block.timestamp
, block.prevrandao
, msg.sender
, and eggCounter
to determine if a player finds an egg. This approach introduces vulnerabilities that allow malicious users to manipulate or predict the outcome, undermining the game's fairness and security.
The PRNG formula:
is vulnerable to manipulation and front-running due to:
block.timestamp
: Set by miners and can be manipulated within a small window (±15 seconds). Attackers can time transactions to exploit this.
msg.sender
: The attacker can control this by using multiple addresses to precompute and choose the optimal one.
eggCounter
: A predictable state variable that increments only when an egg is found. Attackers can observe its current value and compute the random number in advance.
An attacker can:
Precompute the random number for multiple addresses (using known block.prevrandao
, block.timestamp
, and eggCounter
).
Select the address that guarantees a result below the eggFindThreshold
(e.g., 20%).
Submit a transaction with the chosen address to "win" an egg.
This allows attackers to bypass the 20% chance and reliably find eggs, defeating the game's randomness.
The searchForEgg
function lacks checks to ensure users are valid participants (e.g., requiring a minimum stake or NFT ownership). This increases the risk of spam attacks and abuse.
Loss of Fairness: Attackers can manipulate the outcome, making the game unfair for legitimate users.
Gas War Exploits: Malicious users may engage in gas bidding wars to control block timestamps or transaction order, further destabilizing the system.
Financial Loss: The game’s value diminishes if users lose trust in its fairness.
Solidity Static Analysis
Manual Code Review
Security Patterns for Random Number Generation
Replace the PRNG with a Chainlink VRF (Verifiable Random Function) or a similar oracle service. These provide:
Unpredictability: Randomness is generated off-chain and verified on-chain.
Tamper-Proof: Attackers cannot precompute or influence the result.
Add checks to ensure users meet criteria (e.g., holding an NFT or paying a fee) before participating.
Block variables like block.timestamp
, block.prevrandao
, and msg.sender
should never be used alone for critical randomness.
Avoid using mutable state variables (e.g., eggCounter
) in the random number calculation. Instead, use a fixed seed or a secure RNG output.
Attack Steps:
Observe eggCounter
and block.prevrandao
(from the previous block).
Precompute the random number for multiple addresses.
Choose an address where the random result is below eggFindThreshold
.
Submit a transaction with that address to guarantee an egg.
Mitigation Check:
Replace the PRNG with Chainlink VRF:
The current PRNG implementation is insecure and exploitable. Adopting a verifiable random number generator like Chainlink VRF is critical to ensure fairness and prevent manipulation.
Insecure methods to generate pseudo-random numbers
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.