Eggstravaganza

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

Reentrancy Vulnerability in mintEgg() function Allows Unauthorized Multiple Mints

Summary

The mintEgg() function in the EggstravaganzaNFT contract is vulnerable to a classic reentrancy attack. The function updates totalSupply after calling the external _mint() function, which can trigger a reentrant call to mintEgg() via onERC721Received() if the recipient is a contract. This allows a malicious contract to mint multiple NFTs in a single transaction, bypassing supply tracking.

Vulnerability Details

function mintEgg(address to, uint256 tokenId) external returns (bool) {
require(msg.sender == gameContract, "Unauthorized minter");
_mint(to, tokenId); // External call triggers ERC721 receiver
totalSupply += 1; // State updated AFTER external call
return true;
}

Since _mint() calls onERC721Received() if to is a contract, and this happens before totalSupply is updated, a malicious receiver can re-enter mintEgg() and mint unlimited tokens before the state update occurs.

A malicious contract was deployed with a custom onERC721Received() function that calls back into mintEgg() during the receive hook:

function onERC721Received(...) external returns (bytes4) {
if (!attacked) {
attacked = true;
for (uint i = 0; i < 3; i++) {
nft.mintEgg(address(this), 100 + i);
}
}
return this.onERC721Received.selector;
}

Impact

• An attacker can mint multiple NFTs in a single transaction.

• Total supply tracking becomes inaccurate.

• Potentially breaks rarity mechanics or rewards tied to unique token counts.

• Can be used to farm eggs unfairly or spam the system.

Tools Used

• Manual code review

• Foundry tests to simulate reentrant minting

Recommendations

Update the mintEgg() function to increment totalSupply before the _mint() call to prevent reentrancy:

function mintEgg(address to, uint256 tokenId) external returns (bool) {
require(msg.sender == gameContract, "Unauthorized minter");
totalSupply += 1; // Safe state update
\_mint(to, tokenId);
return true;
}

Additionally:

• Consider using ReentrancyGuard for further protection.

Updates

Lead Judging Commences

m3dython Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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