Normal behaviour: redeemMemorabilia() should allow exactly maxSupply unique NFTs to be minted from each collection.
Issue: The guard require(collection.currentItemId < collection.maxSupply) prevents minting when currentItemId equals maxSupply. Because currentItemId starts at 1, only maxSupply – 1 items can ever be redeemed; the last slot is unreachable.
Likelihood:
Any collection with maxSupply ≥ 2 will eventually attempt to mint the final item.
The final buyer will encounter a revert once the penultimate token has been redeemed.
Impact:
One promised NFT in every collection can never be created, frustrating collectors and misreporting sold-out status.
If BEAT tokens were pre-burned for the failed redemption (future feature), users would lose funds.
Steps executed in the Forge test test_PoC_OffByOne_Memorabilia():
Alice acquires a BACKSTAGE pass to have enough BEAT balance.
The organiser creates a new collection with maxSupply = 2.
Alice redeems the first item – success.
Alice immediately attempts to redeem what should be the second and final item. The call reverts with “Collection sold out” although only one NFT exists.
Two straightforward fixes:
or, during collection creation, start the counter at zero and switch to pre-increment so it naturally ranges 1..maxSupply:
Both approaches guarantee that exactly maxSupply NFTs are redeemable.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.