Eggstravaganza

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

`EggstravaganzaNFT` Contract Neglects Safe Minting Method

Summary

The EggstravaganzaNFT contract uses the _mint function instead of _safeMint, bypassing critical recipient checks when minting NFTs. This can result in NFTs being permanently lost if sent to a contract that cannot handle ERC721 tokens.

Vulnerability Details

Vulnerability Exists in Line 29 of EggstravaganzaNFT Code: https://github.com/CodeHawks-Contests/2025-04-eggstravaganza/blob/main/src/EggstravaganzaNFT.sol#L29

EggstravaganzaNFT contract requires the caller; e.g: minter in mintEgg function to be the EggHuntGame contract which in return mints the token to the player address and whether the player address is an externally Owned Account or a contract; it's safer and recommended to check if the recipient is aware and can accept the ERC721 transfer or not.

Since _mint function does not check whether the recipient can properly handle ERC721 tokens, NFTs could be irreversibly lost.

function _mint(address to, uint256 tokenId) internal {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}

By contrast, _safeMint function includes a check using onERC721Received, ensuring safe transfer:

function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
_mint(to, tokenId);
ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);
}

Impact

Despite the fact that the call sender msg.sender in EggstravaganzaNFT contract is the EggHuntGame contract, the fact that the actual receiver of the NFT is the player which may be a contract address; without implementing the acceptance check on the receiver address will result in permanently losing the NFT when minted to player.

Tools Used

Manual and Visual Code Inspection

Recommendations

Using _safeMint ensures compatibility and prevents accidental loss of NFTs due to non-compliant recipient contracts.

function mintEgg(address to, uint256 tokenId) external returns (bool) {
require(msg.sender == gameContract, "Unauthorized minter");
_safeMint(to, tokenId);
totalSupply += 1;
return true;
}
Updates

Lead Judging Commences

m3dython Lead Judge 5 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Unsafe ERC721 Minting

Protocol doesn't check if recipient contracts can handle ERC721 tokens

Support

FAQs

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