Beatland Festival

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

Final NFT in Memorabilia Collection Cannot Be Redeemed Due to Strict Less-Than Check

Root + Impact

Descriptionredeem

The Memorabilia mints NFTs until maxSupply is reached. The problem is The check currentItemId < maxSupply prevents minting the final item.

// FestivalPass.sol
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"); // @> Excludes final item
// ...
}

Risk

Likelihood:

  • Occurs naturally when nearing max supply.

  • Inherent logic error.

Impact:

  • No funds at risk.

  • Minor functionality issue (one fewer NFT per collection

Proof of Concept

// In FestivalPassTest.sol
function test_MemorabiliaOffByOne() public {
// Create collection with maxSupply = 2
vm.prank(organizer);
uint256 collectionId = festivalPass.createMemorabiliaCollection(
"Limited Edition", "ipfs://QmLimited", 50e18, 2, true
);
// Fund user1
vm.prank(address(festivalPass));
beatToken.mint(user1, 100e18);
// Redeem first item
vm.prank(user1);
festivalPass.redeemMemorabilia(collectionId);
assertEq(festivalPass.balanceOf(user1, festivalPass.encodeTokenId(collectionId, 1)), 1);
(, , , , uint256 currentItemId, ) = festivalPass.collections(collectionId);
assertEq(currentItemId, 2);
// Try to redeem second item (fails)
vm.prank(user1);
vm.expectRevert("Collection sold out");
festivalPass.redeemMemorabilia(collectionId);
}

Recommended Mitigation

// FestivalPass.sol
function redeemMemorabilia(uint256 collectionId) external {
// ...
- require(collection.currentItemId < collection.maxSupply, "Collection sold out");
+ require(collection.currentItemId <= collection.maxSupply, "Collection sold out");
// ...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 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.