Beatland Festival

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

Organizer Cannot Deactivate Redemption for Sold-Out Memorabilia Collections

Organizer Cannot Deactivate Redemption for Sold-Out Memorabilia Collections, Leading to Unclear or Stale UI States

Description

  • The redeemMemorabilia function checks that the collection is marked as active and that the currentItemId has not yet reached maxSupply

  • Once the collection reaches full supply, the function reverts with Collection sold out and there is no way for the organizer to manually deactivate the collection. Leading wastage of gas for users who further tries to redeem memorabilia based on its active state.

// Root cause in the codebase with @> marks to highlight the relevant section
@> 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");
...
}

Risk

Likelihood:

  • Medium – This is likely to occur especially with popular collections reaching full supply.

Impact:

  • Causes confusion among users.

  • Creates a denial-of-service (DoS) situation for the final redeem call if multiple users attempt redemption concurrently—only one will succeed, and the rest will revert even though the collection remains shown as active.

Proof of Concept

  1. Organizer creates a memorabilia collection with activateNow = true and maxSupply = 10.

  2. Users redeem up to 10 items.

  3. On the 10th redemption, currentItemId == maxSupply, causing all further redemption attempts to fail with Collection sold out.

  4. The collection remains isActive == true, making the UI or external tools think it’s still redeemable.

Recommended Mitigation

  1. Allow the organizer to deactivate a collection manually.

  2. Optionally, set isActive = false automatically once currentItemId == maxSupply during the last successful redemption:

+ function deactivateCollection(uint256 collectionId) external onlyOrganizer {
+ collections[collectionId].isActive = false;
+ emit CollectionDeactivated(collectionId);
+ }
+ if (collection.currentItemId + 1 == collection.maxSupply) {
+ collection.isActive = false;
+ }
Updates

Lead Judging Commences

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

createMemorabiliaCollection with isActive false for later usage - flow not properly implemented.

Low because an organizer can use it with active = true and organizer is trusted.

Support

FAQs

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