**Description:** The `EggHuntGame` contract's searchForEgg function is vulnerable due to its weak pseudo-random number generator combined with the lack of rate-limiting. An attacker can deploy a contract that repeatedly calls searchForEgg until the weak randomness check passes. The provided `weakRandomUnrestrictedCall` function, leverages this vulnerability by generating a pseudo-random number based on block data and the contract’s address. If the generated number falls below the configured eggFindThreshold, the attacker’s contract calls searchForEgg to mint an egg NFT. This approach allows the attacker to significantly skew the game's fairness by repeatedly triggering egg minting.
**Impact:** An attacker can abuse this vulnerability by spamming calls to `searchForEgg`, which leads to:
• An unfair advantage resulting in a disproportionate number of eggs minted for the attacker.
• Disruption of the intended game mechanics and balance, potentially devaluing rewards for honest participants.
• Increased network and gas costs due to a high volume of state-changing transactions that compromise the system's overall stability.
**Proof of Concept:** Below is the vulnerable function that demonstrates the attack vector:
```solidity
function weakRandomUnrestrictedCall() public {
uint256 eggFindThreshold = game.eggFindThreshold();
uint256 eggCounter = game.eggCounter();
uint256 random =
uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, address(this), eggCounter))) % 100;
// If the random number is less than the threshold, an egg is minted via searchForEgg.
if (random < eggFindThreshold) {
game.searchForEgg();
}
}
```
This snippet shows how an attacker can manipulate inputs to repeatedly trigger searchForEgg when the pseudo-random outcome is favorable. An attacker could wrap this function call in a loop (or repeatedly invoke it over multiple transactions) until successfully minting eggs, thereby undermining the intended random distribution of rewards.
**Recommended Mitigation:**
• Implement Robust Randomness: Replace the weak pseudo-random number generation with a secure randomness source such as Chainlink VRF or a commit-reveal scheme to ensure unpredictability.
• Introduce Rate-Limiting/Cooldown: Enforce a per-user cooldown period or rate limit for calling searchForEgg, so that even if randomness is manipulated, an attacker cannot spam the function calls in rapid succession:
```diff
contract EggHuntGame is Ownable {
+ uint256 public constant COOLDOWN_PERIOD = 30; // seconds
+ mapping(address => uint256) public lastSearchTime;
...
}
```
```diff
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] + COOLDOWN_PERIOD, "Cooldown active");
+ lastSearchTime[msg.sender] = block.timestamp;
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]);
}
}
```