Beatland Festival

First Flight #44
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: medium
Valid

Incorrect Memorabilia Supply Check

Description

  • currentItemId < maxSupply should be <=.

function redeemMemorabilia(uint256 collectionId) external {
MemorabiliaCollection storage collection = collections[collectionId];
require(collection.priceInBeat > 0, "Collection does not exist");
require(collection.isActive, "Collection not active");
@> require(collection.currentItemId < collection.maxSupply, "Collection sold out");
// Burn BEAT tokens
BeatToken(beatToken).burnFrom(msg.sender, collection.priceInBeat);
// Generate unique token ID
uint256 itemId = collection.currentItemId++;
uint256 tokenId = encodeTokenId(collectionId, itemId);
// Store edition number
tokenIdToEdition[tokenId] = itemId;
// Mint the unique NFT
_mint(msg.sender, tokenId, 1, "");
emit MemorabiliaRedeemed(msg.sender, tokenId, collectionId, itemId);
}

Risk

Likelihood:

  • Likely to occur during setup but limited to 1 NFT loss.

Impact:

  • 1 less NFT minted than intended.

Proof of Concept

function test_MemorabiliaSupply() public {
// Create collection: maxSupply=3
uint256 collectionId = festivalPass.createMemorabiliaCollection(...);
// Redeem 3 NFTs
for (uint i; i < 3; i++) {
festivalPass.redeemMemorabilia(collectionId);
}
// 4th redeem fails though maxSupply=3
vm.expectRevert("Collection sold out");
festivalPass.redeemMemorabilia(collectionId); // Should allow 3

Recommended Mitigation

- require(collection.currentItemId < collection.maxSupply, "Collection sold out");
+ require(collection.currentItemId <= collection.maxSupply, "Sold out");
Updates

Lead Judging Commences

inallhonesty Lead Judge about 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Off by one error in redeemMemorabilia

Support

FAQs

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