Summary
The EggHuntGame contract fails to properly initialize critical dependencies (EggVault and EggstravaganzaNFT) during deployment. This oversight renders core features (NFT minting and vault deposits) permanently inoperable.
Vulnerability Details
1. Missing Initialization Calls in Constructor
constructor(address _eggNFTAddress, address _eggVaultAddress) Ownable(msg.sender) {
eggNFT = EggstravaganzaNFT(_eggNFTAddress);
eggVault = EggVault(_eggVaultAddress);
}
2. Unconfigured Permissions in Dependent Contracts
function mintEgg(address to, uint256 tokenId) external returns (bool) {
require(msg.sender == gameContract, "Unauthorized minter");
}
function depositEgg(uint256 tokenId, address depositor) public {
require(address(eggNFT) != address(0), "NFT contract not set");
}
Impact
• Permanent failure of NFT minting functionality
• Complete lockout of vault deposit system
• Protocol becomes completely non-functional
• Requires emergency redeployment
Tools Used
• Manual code review
• Slither (detected uninitialized storage variables)
• Foundry test proving failed initialization:
function testInitializeFailure() public {
vm.expectRevert("Unauthorized minter");
game.searchForEgg();
}
Recommendations
1. Complete Initialization Chain
constructor(address _eggNFTAddress, address _eggVaultAddress) Ownable(msg.sender) {
eggNFT = EggstravaganzaNFT(_eggNFTAddress);
eggVault = EggVault(_eggVaultAddress);
eggNFT.setGameContract(address(this));
eggVault.setEggNFT(_eggNFTAddress);
}
2. Add Initialization Verifier
modifier systemInitialized() {
require(eggNFT.gameContract() == address(this), "NFT not initialized");
require(address(eggVault.eggNFT()) != address(0), "Vault not initialized");
_;
}
function searchForEgg() external systemInitialized { ... }
function depositEggToVault() external systemInitialized { ... }
3. Implement Fail-Safe Checks
function setEggNFT(address _eggNFTAddress) external onlyOwner {
require(eggNFT.totalSupply() == 0, "Cannot change after minting");
}