collectionCirculationSupply is incremented in each mint and it's used to check if the mint don't overtakes the collection's max supply. However, it increments before the check, which makes that although last token is in the max supply range, the collectionCirculationSupply becomes a value higher than max supply, not allowing the mint. Even further, the code doesn't revert or refund funds if that happens.
Proof of Concept
Let's exemplify:
I want to mint the last token of the collection (the token 200)
collectionTotalSupply = 200
collectionCirculationSupply = 200. The variable is designed to be the next ID to mint, which is 200 in the example case because we will mint the token 200 of the collection. The following line is used everytime the protocol wants to know the next ID to mint:
After, it checks if it's higher than the collectionTotalSupply:
if (collectionAdditionalData[_collectionID].collectionTotalSupply >= collectionAdditionalData[_collectionID].collectionCirculationSupply)
collectionTotalSupply (200) >= collectionCirculationSupply (201), which is FALSE
So, the last token of the supply will not be minted. However, even worse is the fact that the if is the only check, there is no else to revert the transaction or any code to refund the user.
Impact
The collection will have a token less, which is a loss of funds for the collection. Also, the one to mint the last token will lose all his money without refunds.
Likelihood: Medium.
Impact: High.
Risk: High (Medium Likelihood + High Impact)
Tools Used
Manual Review
Recommended Mitigation Steps
The collectionTotalSupply increment needs to be after the checks.
The check needs to revert, so user doesn't lose money.
Lines of code
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L181 https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L192 https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L217
Vulnerability details
Description
collectionCirculationSupply
is incremented in each mint and it's used to check if the mint don't overtakes the collection's max supply. However, it increments before the check, which makes that although last token is in the max supply range, thecollectionCirculationSupply
becomes a value higher than max supply, not allowing the mint. Even further, the code doesn't revert or refund funds if that happens.Proof of Concept
Let's exemplify:
collectionTotalSupply = 200
collectionCirculationSupply = 200
. The variable is designed to be the next ID to mint, which is 200 in the example case because we will mint the token 200 of the collection. The following line is used everytime the protocol wants to know the next ID to mint:I call
mint
, which callsmint
fromNextGenCore.sol
:First, it increments the
collectionCirculationSupply
:collectionCirculationSupply = 200 + 1 = 201
After, it checks if it's higher than the
collectionTotalSupply
:collectionTotalSupply (200) >= collectionCirculationSupply (201)
, which isFALSE
So, the last token of the supply will not be minted. However, even worse is the fact that the
if
is the only check, there is noelse
to revert the transaction or any code to refund the user.Impact
The collection will have a token less, which is a loss of funds for the collection. Also, the one to mint the last token will lose all his money without refunds.
Tools Used
Manual Review
Recommended Mitigation Steps
collectionTotalSupply
increment needs to be after the checks.Assessed type
ERC721