Beatland Festival

First Flight #44
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

The NFT will not be displayed in the market place

Root + Impact

Description

  • The uri() function in FestivalPass.sol does not append the required .json extension to the metadata URIs. This causes NFT marketplaces and wallets to fail when attempting to fetch metadata, as they expect properly formatted JSON metadata files with the .json extension.


function uri(uint256 tokenId) public view override returns (string memory) {
// Handle regular passes (IDs 1-3)
if (tokenId <= BACKSTAGE_PASS) {
@> return string(abi.encodePacked("ipfs://beatdrop/", Strings.toString(tokenId)));
}
// Decode collection and item IDs
(uint256 collectionId, uint256 itemId) = decodeTokenId(tokenId);
// Check if it's a valid memorabilia token
if (collections[collectionId].priceInBeat > 0) {
// Return specific URI for this item
// e.g., "ipfs://QmXXX/metadata/5" for item #5
return string(abi.encodePacked(
collections[collectionId].baseUri,
"/metadata/",
@> Strings.toString(itemId)
));
}
return super.uri(tokenId);
}

Risk

Likelihood:

  • This will occur anytime the URI function is used to resolve the metadata of the NFT.

Impact:

  • NFTs will not display properly in marketplaces like OpenSea, Rarible, or other platforms

  • Wallet applications may fail to show NFT metadata, including name, description, and images

  • Users will see broken or missing NFT information, significantly degrading the user experience

Proof of Concept

In the uri() function, the code constructs URIs without the .json extension:

return string(abi.encodePacked("ipfs://beatdrop/", Strings.toString(tokenId)));
// For memorabilia items
return string(abi.encodePacked(
collections[collectionId].baseUri,
"/metadata/",
Strings.toString(itemId)
));

Recommended Mitigation


The remedy is to append .json extension to all metadata URIs: Standard NFT metadata URIs should end with .json to be properly recognized by marketplaces and wallets.

if (tokenId <= BACKSTAGE_PASS) {
- return string(abi.encodePacked("ipfs://beatdrop/", Strings.toString(tokenId)));
}
- if (collections[collectionId].priceInBeat > 0) {
- return string(abi.encodePacked(
- collections[collectionId].baseUri,
- "/metadata/",
- Strings.toString(itemId)
- ));
- }
if (tokenId <= BACKSTAGE_PASS) {
+ return string(abi.encodePacked("ipfs://beatdrop/", Strings.toString(tokenId), ".json"));
}
+ if (collections[collectionId].priceInBeat > 0) {
+ return string(abi.encodePacked(
+ collections[collectionId].baseUri,
+ "/metadata/",
+ Strings.toString(itemId),
+ ".json"
+ ));
+ }
Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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