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 9 months 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!