Eggstravaganza

First Flight #37
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Valid

Insecure Random Number Generation

Summary

The EggHuntGame contract uses an insecure random number generation mechanism that relies on predictable blockchain variables. This vulnerability allows attackers to potentially manipulate or predict the outcome of egg searches, compromising the fairness and integrity of the game.

Vulnerability Details

The random number generation in the searchForEgg() function uses a combination of block.timestamp, block.prevrandao, msg.sender, and eggCounter as entropy sources:

uint256 random = uint256(
keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender, eggCounter))
) % 100;

These sources are problematic because:

  1. block.timestamp can be manipulated by miners within a small range

  2. block.prevrandao (formerly known as block.difficulty) is also predictable

  3. The combination of these values creates a pseudo-random number that is vulnerable to exploitation

An attacker can:

  • Calculate the expected random value in advance

  • Time their transactions to coincide with favorable random outcomes

  • Potentially gain an unfair advantage in finding eggs compared to other players

Impact

This vulnerability has significant impact on the game's fairness and economy:

  1. Players can manipulate the randomness to consistently find eggs at a higher rate than intended

  2. The game's scarcity mechanism is compromised, potentially devaluing the NFTs

  3. The core gameplay mechanic becomes exploitable, undermining the entire game experience

  4. Trust in the game's fairness is eroded, potentially leading to player abandonment

Tools Used

  • Manual code review

  • Solidity compiler analysis

  • Foundry testing framework

Recommendations

  1. Implement a more secure randomness source such as Chainlink VRF (Verifiable Random Function)

  2. Consider a commit-reveal scheme where users commit to actions before the random value is generated

  3. If external oracles aren't feasible, implement a multi-block confirmation pattern to make manipulation more difficult

  4. Add time delays between user actions to prevent rapid exploitation attempts

Example implementation with Chainlink VRF:

// Add Chainlink VRF imports and interfaces
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
// Modify contract to inherit from VRFConsumerBase
contract EggHuntGame is Ownable, VRFConsumerBase {
bytes32 internal keyHash;
uint256 internal fee;
mapping(bytes32 => address) public requestIdToSender;
constructor(...) VRFConsumerBase(
vrfCoordinator,
linkToken
) {
keyHash = _keyHash;
fee = _fee;
}
function searchForEgg() external {
require(gameActive, "Game not active");
require(block.timestamp >= startTime, "Game not started yet");
require(block.timestamp <= endTime, "Game ended");
// Request randomness from Chainlink VRF
bytes32 requestId = requestRandomness(keyHash, fee);
requestIdToSender[requestId] = msg.sender;
}
// Callback function used by VRF Coordinator
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
address player = requestIdToSender[requestId];
uint256 random = randomness % 100;
if (random < eggFindThreshold) {
eggCounter++;
eggsFound[player] += 1;
eggNFT.mintEgg(player, eggCounter);
emit EggFound(player, eggCounter, eggsFound[player]);
}
}
}
Updates

Lead Judging Commences

m3dython Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Insecure Randomness

Insecure methods to generate pseudo-random numbers

Support

FAQs

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