Incorrect higher mint price for the first token minted in each generation starting from the second generation #646
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
duplicate-564
edited-by-warden
🤖_03_group
AI based duplicate group recommendation
satisfactory
satisfies C4 submission criteria; eligible for awards
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L190
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L193
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L282
Vulnerability details
Summary
Users will need to pay a higher price to mint the first token for each generation starting from generaton 2, instead of the
0.005 ether
starting price. This is because theTraitForgeNft.currentGeneration
variable isn't incremented on the10_000
th mint of each generation. It is incremented on the10_001
th mint (basically, the first mint of the next generation). So on the first mint of the next generation, theTraitForgeNft
contract still assumes to be in the last generation and calculates a wrong mint price which is higher than0.005 ether
. Only then is theTraitForgeNft.currentGeneration
variable incremented. This is applicable to bothTraitForgeNft::mintToken()
andTraitForgeNft::mintWithBudget()
functions.Vulnerability Details
Let's see two code segments, one from
TraitForgeNft::mintToken()
and the other fromTraitForgeNft::_mintInternal()
function,The price for minting is calculated first.
Links:
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L190
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L193
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L282.
The current generation is incremented after price calculation for the mint. Thus, while moving from one generation to the next, the contract still thinks it's in the last generation during the price calculation phase, and gives an incorrect high price when it should be
0.005 ether
instead. Then theTraitForgeNft.currentGeneration
value is incremented and the contract functions as expected from the second mint of the next generation.This issue is applicable to
TraitForgeNft::mintWithBudget()
function as well. However, it currently has a bug which doesn't allow minting beyond the first generation.Link:
https://github.com/code-423n4/2024-07-traitforge/blob/279b2887e3d38bc219a05d332cbcb0655b2dc644/contracts/TraitForgeNft/TraitForgeNft.sol#L215
If the number of token ids minted goes beyond
TraitForgeNft.maxTokensPerGen
, the function will not mint further, however, this is a finding on its own. If this was to be resolved, the function would also be susceptible to the same problem while minting the first token in each generation starting from generation 2.Impact
Users will need to pay an incorrect/high amount for minting the first token for each generation starting from generation 2 instead of the
0.005 ether
starting price. This essentially causes a fund loss for users (paying higher instead of 0.005 ether). Also, the amount to pay for the first token of each generation continues to become larger and larger as the generations progress (due to theTraitForgeNft.priceIncrement
variable increasing byTraitForgeNft.priceIncrementByGen
each generation). However, the fund loss is only limited to 9 mints upto the 10th generation.Proof of Concept
To write the PoC, some changes had to be made to the
TraitForgeNft
contract to stay within the block gas limit and avoid a revert due to another issue highlighted below.The following changes were made to write the PoC for this finding.
Changed the
TraitForgeNft.maxTokensPerGen
variable from1e4
to1e3
, to avoidOutOfGas
error.Commented out the following line from
TraitForgeNft::_incrementGeneration()
function because it causes a revert, and is a completely different finding on its own. Here, theTraitForgeNft
contract tries to re-initialize the alpha indices in theEntropyGenerator
contract -- the slots which hold the God entropy value of999999
. However, it will always revert becauseTraitForgeNft
isn't the owner ofEntropyGenerator
contract andEntropyGenerator::initializeAlphaIndices()
function has anonlyOwner
modifier.We will be using the following setup to write PoCs in Foundry,
Now run the following test case,
The test passes with the following logs,
Tools Used
Manual review. Foundry for writing the PoC.
Recommended Mitigation
Increment the generation before calculating the price.
Make the following changes in
TraitForgeNft::mintToken()
function,Remember, the finding is also valid for
TraitForgeNft::mintWithBudget()
function, so changes need to be made there as well.Let's unit test the
TraitForgeNft::mintToken()
function (in Foundry),The unit test passes with the following logs,
Assessed type
Other
The text was updated successfully, but these errors were encountered: