# Off-by-One Error in Memorabilia Supply Cap; Last Item Cannot Be Minted
## Description
Normally, the collection should allow minting **up to `maxSupply`** items.
The current check uses `< maxSupply`, but `currentItemId` starts at 1, so the last item (with `ID == maxSupply`) can **never be minted**.
```javascript
function redeemMemorabilia(uint256 collectionId) external {
...
require(collection.currentItemId < collection.maxSupply, "Collection sold out");
...
uint256 itemId = collection.currentItemId++;
...
}
```
## Risk
### Likelihood
* This will occur **every time a collection reaches its maximum supply**.
* The **last item** in every collection will be **unmintable**.
### Impact
* Users are **unable to mint the final item**, reducing actual supply below the intended cap.
* Potential **user frustration** and **loss of trust**.
## Proof of Concept
If `maxSupply` is 5, only items `1–4` can be minted.
When `currentItemId == 5`, the check fails, and the function reverts.
### Proof of Code
Add the following code into the test suite.
```javascript
function test_OffByOne_MemorabiliaSupplyCap() public {
// Setup: Give user BEAT tokens
vm.prank(address(festivalPass));
beatToken.mint(user1, 1000e18);
// Organizer creates a memorabilia collection with maxSupply = 3
vm.prank(organizer);
uint256 collectionId = festivalPass.createMemorabiliaCollection("OffByOne", "ipfs://offbyone", 100e18, 3, true);
// User redeems memorabilia up to the cap
vm.startPrank(user1);
festivalPass.redeemMemorabilia(collectionId); // itemId = 1
festivalPass.redeemMemorabilia(collectionId); // itemId = 2
// Third redemption should fail due to off-by-one bug (should allow 3, but only allows 2)
vm.expectRevert("Collection sold out");
festivalPass.redeemMemorabilia(collectionId);
vm.stopPrank();
// Check that only 2 items were minted, not 3
uint256 tokenId1 = festivalPass.encodeTokenId(collectionId, 1);
uint256 tokenId2 = festivalPass.encodeTokenId(collectionId, 2);
uint256 tokenId3 = festivalPass.encodeTokenId(collectionId, 3);
assertEq(festivalPass.balanceOf(user1, tokenId1), 1);
assertEq(festivalPass.balanceOf(user1, tokenId2), 1);
assertEq(
festivalPass.balanceOf(user1, tokenId3),
0,
"Should not be able to mint the last item due to off-by-one error"
);
}
```
## Recommended Mitigation
Change the check to allow minting **up to and including** `maxSupply`:
```diff
- require(collection.currentItemId < collection.maxSupply, "Collection sold out");
+ require(collection.currentItemId <= collection.maxSupply, "Collection sold out");
```