Eggstravaganza

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

Lack of rate limiting in searchForEgg allows unlimited attempts in a single transaction

Summary

The EggHuntGame::searchForEgg function has no rate limiting or transaction-level protection, allowing attackers to make multiple attempts in a single transaction until they successfully find an egg, completely bypassing the intended randomness mechanism.

Vulnerability Details

The vulnerability exists in the searchForEgg function which has no protection against being called multiple times in a single transaction:

## EggHuntGame.sol
function searchForEgg() external {
require(gameActive, "Game not active");
require(block.timestamp >= startTime, "Game not started yet");
require(block.timestamp <= endTime, "Game ended");
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]);
}
}

An attacker can create a contract that calls this function multiple times in a loop until an egg is found. With each attempt, a new random number is generated, giving the attacker multiple chances to find an egg within a single transaction.

Proof of Concept

  1. Attacker deploys a contract with a function that calls searchForEgg in a loop

  2. The function continues calling searchForEgg until an egg is found

  3. With each attempt, the probability of finding an egg increases cumulatively

  4. With enough attempts, the attacker can virtually guarantee finding an egg regardless of how low the eggFindThreshold is set

With this attack, the probability of finding an egg approaches 100% as the number of attempts increases:

  • With a 20% chance per attempt: 10 attempts gives an 89% chance of success

  • With a 30% chance per attempt: 10 attempts gives a 97% chance of success

  • With a 50% chance per attempt: 10 attempts gives a 99.9% chance of success

Impact

  • Completely bypasses the randomness mechanism of the game

  • Allows attackers to guarantee finding eggs regardless of the probability threshold

  • Creates an unfair advantage for technical players who can exploit this vulnerability

  • Could lead to excessive minting of NFTs in a single transaction

  • Undermines the core game mechanics and intended rate limiting

  • Combines with the predictable randomness issue to make the game completely exploitable

Tools Used

  • Manual code review

Recommendations

Implement a cooldown period between attempts for each address:

+ mapping(address => uint256) public lastSearchTime;
+ uint256 public constant SEARCH_COOLDOWN = 1 hours;
function searchForEgg() external {
require(gameActive, "Game not active");
require(block.timestamp >= startTime, "Game not started yet");
require(block.timestamp <= endTime, "Game ended");
+ require(block.timestamp >= lastSearchTime[msg.sender] + SEARCH_COOLDOWN, "Too soon to search again");
+ lastSearchTime[msg.sender] = block.timestamp;
// ... rest of function ...
}
Updates

Lead Judging Commences

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

No rate limiting

Contract lacks any cooldown mechanism, search limits, or costs in the searchForEgg() function

Support

FAQs

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