Snowman Merkle Airdrop

AI First Flight #10
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

# All NFTs Have Identical Metadata — Fungible NFT Issue

Root + Impact

Description

  • Normal behavior: Each NFT minted should have unique metadata (name, attributes, image) that distinguishes it from other tokens.

  • Issue: The tokenURI() function currently returns static metadata and a single image URI for all tokens, making every NFT identical and therefore fungible.

// Root cause in the codebase with @> marks to highlight the relevant section
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
@> string memory imageURI = s_SnowmanSvgUri;
@> return string(
@> abi.encodePacked(
@> _baseURI(),
@> Base64.encode(
@> abi.encodePacked(
@> '{"name":"',
@> name(),
@> '", "description":"Snowman for everyone!!!", ',
@> '"attributes": [{"trait_type": "freezing", "value": 100}], "image":"',
@> imageURI,
@> '"}'
@> )
@> )
@> )
@> );
}
Risk
Likelihood:
This occurs for every token minted, as the metadata is static and does not depend on tokenId.
Any wallet or marketplace will display the same image and attributes for all NFTs.
Impact:
All NFTs are fungible, losing the intended uniqueness.
Reduces collector value and can mislead users regarding the NFT collection’s originality.
```solidity
function testAllNFTsAreFungible() public {
address user1 = makeAddr("user1");
address user2 = makeAddr("user2");
snowmanContract.mintSnowman(user1, 1);
snowmanContract.mintSnowman(user2, 1);
string memory uri1 = snowmanContract.tokenURI(0);
string memory uri2 = snowmanContract.tokenURI(1);
// Both tokenURIs are identical
assertEq(uri1, uri2);
}

Recommended Mitigation

  • string memory imageURI = s_SnowmanSvgUri;

  • string memory imageURI = string(abi.encodePacked(s_SnowmanSvgUri, "/", Strings.toString(tokenId), ".svg"));

  • '{"name":"', name(), '", "description":"Snowman for everyone!!!", ',

  • '{"name":"Snowman #', Strings.toString(tokenId), '", "description":"Unique Snowman NFT", ',

  • '"attributes":[{"trait_type":"freezing","value":', Strings.toString(tokenId % 100), '}], ',

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 12 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!