The EggVault and EggHuntGame contracts are vulnerable to reentrancy attacks due to unprotected external calls to the EggstravaganzaNFT contract. This vulnerability allows an attacker to repeatedly execute critical functions before state updates occur, potentially draining NFTs from the Vault or disrupting deposit logic.
The reentrancy vulnerabilities appear in the following functions:
EggVault.withdrawEgg():
solidity
CollapseWrapCopy
eggNFT.transferFrom(address(this), msg.sender, tokenId)``;
storedEggs[tokenId] = false``;
delete eggDepositors[tokenId]``;
The external call eggNFT.transferFrom occurs before state updates (storedEggs and eggDepositors), allowing a malicious NFT contract to reenter withdrawEgg.
EggHuntGame.depositEggToVault():
solidity
CollapseWrapCopy
eggNFT.transferFrom(msg.sender, address(eggVault), tokenId); eggVault.depositEgg(tokenId, msg.sender);
The eggNFT.transferFrom call could trigger a callback, potentially reentering the contract before eggVault.depositEgg updates the Vault state.
These issues arise because:
The EggstravaganzaNFT contract inherits from OpenZeppelin’s ERC721, which calls _beforeTokenTransfer. If overridden with malicious logic, it could reenter the calling contract.
No reentrancy protection (e.g., nonReentrant modifier) is present in either function.
An attacker can:
Deploy a malicious NFT contract mimicking EggstravaganzaNFT.
Trigger reentrancy by calling withdrawEgg or depositEggToVault, repeatedly executing the function before state is finalized.
This vulnerability has severe consequences:
NFT Theft: In EggVault, an attacker could withdraw the same NFT multiple times, draining the Vault.
State Corruption: In EggHuntGame, reentrancy during deposit could disrupt Vault synchronization, allowing unauthorized NFT control.
Loss of Trust: Exploits could undermine confidence in the system, leading to player loss.
Economic Damage: Stolen or duplicated NFTs could crash their market value.
Manual code review
Solidity compiler analysis (version ^0.8.23)
Theoretical attack simulation with reentrant contract patterns
Add Reentrancy Protection:
Use OpenZeppelin’s ReentrancyGuard with the nonReentrant modifier.
Update State Before External Calls:
Ensure state changes precede external interactions.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.