Beatland Festival

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

Off-by-one error prevents last memorabilia redemption

Root + Impact

Off-by-one error prevents last memorabilia redemption

Description

The FestivalPass::redeemMemorabilia function allows users to redeem a unique memorabilia NFT from a limited collection using BEAT tokens. The function uses the currentItemId counter to enforce the supply cap with the following condition:

require(collection.currentItemId < collection.maxSupply, "Collection sold out");

However, because currentItemId starts at 1, this condition excludes the final memorabilia item resulting in an off-by-one and leaving one item unreachable.

Risk

Likelihood: High
The logic runs on every redemptin call and users attempting to redeem up to maxSupply will be blocked by the final one.

Impact: Medium
One memorabilia NFT will be permanently unredeemable per collection, breaking the promise of full supply availability and potentially leading to user frustration and incomplete collections.

Proof of Concept

function test_cannotRedeemLastMemorabilia() public {
uint256 maxSupply = 1;
uint256 priceInBeat = 500e18;
vm.prank(organizer);
uint256 collectionId = festivalPass.createMemorabiliaCollection("Golden Hats", "ipfs://QmGoldenHats", priceInBeat, maxSupply, true);
// Fund account to be able to buy 5 memorabilia
deal(address(beatToken), user1, 5 * priceInBeat);
vm.prank(user1);
vm.expectRevert();
festivalPass.redeemMemorabilia(collectionId);
}

Recommended Mitigation

Use <= instead of < to ensure the last item can be redeemed.

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

Lead Judging Commences

inallhonesty Lead Judge about 1 month 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.