Eggstravaganza

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

Users either have a 100% chance of finding an Eggstravaganza NFT or will never find an Eggstravaganza NFT

Summary

onlyOwner can set the chance at finding an egg in the setEggFindThreshold function, they can then set it to be 100 or less than 100, but nothing above 100. This threshold is then used in the searchForEgg function where if the random number is lower than the threshold than the user finds an egg. The problem is that the random number has a range of 0-99 thanks to modulo operator, which is set to % 100. Which is used to generate a random number. If the onlyOnwer sets the threshold to be 100 then any user that calls the function searchForEgg will find an egg. This can also be said if the threshold is set to 0, but if the threshold is 0 then instead of having a 100% chance of finding an egg. Users will never end up finding an egg.

Vulnerability Details

// @notice Allows the owner to adjust the egg-finding chance.
function setEggFindThreshold(uint256 newThreshold) external onlyOwner {
require(newThreshold <= 100, "Threshold must be <= 100");
eggFindThreshold = newThreshold;
}
/// @notice Participants call this function to search for an egg.
/// A pseudo-random number is generated and, if below the threshold, an egg is found.
function searchForEgg() external {
require(gameActive, "Game not active");
require(block.timestamp >= startTime, "Game not started yet");
require(block.timestamp <= endTime, "Game ended");
// Pseudo-random number generation (for demonstration purposes only)
uint256 random = uint256(
keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender, eggCounter))
) % 100;
if (random < eggFindThreshold) {
eggCounter++;
eggsFound[msg.sender] += 1;
eggNFT.mintEgg(msg.sender, eggCounter);
emit EggFound(msg.sender, eggCounter, eggsFound[msg.sender]);
}

If the threshold is ever set to 100 by onlyOwner then any user can find an egg and mint themselves a Eggstravaganza NFT every time they call the function. This due to the fact that in setEggFindThresehold the require statement allows for the threshold to be set to 100. Then in the searchForEgg function the random number generated has a range of 0-99 thanks to the modulo operator, which is % 100. Then the require statement checks to see if the random number is lower than the threshold. Which will always be true if the the threshold is set to 100. Meaning any user that calls this function will have a 100% chance of finding an egg. The same thing happens if the threshold is 0, but instead of finding an egg the users that call the function will never find an egg. This due to the fact that the random number will never be lower than 0, since it only has a range of 0-99 and the require statement only allows the random number to be lower than threshold and not equal to it.

Impact

Users believe that everyone has a fair and random chance at finding an egg since the eggs are "hidden", but if the conditions above are met some users are able to find eggs and can end up finding all the eggs, while other users who weren't aware end up losing a chance at finding an egg.

Tools Used

Manual Review

Recommendations

Have the newThreshold max be lower than 100 and the minimum be greater than 0. Or you could implement a system with different predefined chances such as "High chance at finding egg(60%)", "Medium chance at finding egg (40%)", "Low chance at finding egg (20%)".

Updates

Lead Judging Commences

m3dython Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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