Submitted by Fulum, also found by DeFiHackLabs, bird-flu, t0x1c, Krace, xAriextz, merlin, phoenixV110, 00xSEV, nuthan2x, zhaojie, xuwinnie, PENGUN, Jorgect, oakcobalt, VAD37, twcctop, Juntao, DanielArmstrong, and evmboi32
A user can mint a token at an incorrect price and lose funds if they mint on the last authorized block.timestamp during a Linear or Exponential Descending Sale Model.
On a Linear or Exponential Descending Sale Model, the admin sets the collectionMintCost and the collectionEndMintCost. In context of these sale models, the collectionMintCost is the price for minting a token at the beginning and the collectionEndMintCost the price at the end of the sale.
The minting methods use the function MinterContract::getPrice() to compute the correct price at the actual timing, check the function with the branch for a Linear or Exponential Descending Sale Model:
We can see that if the collectionPhases[_collectionId].salesOption == 2 (its the number for a descending sale model), and if the block.timestamp is > allowlistStartTime and < publicEndTime. The price is correctly computed.
A little check on the mint() function:
But if the publicEndTime is strictly equal to publicEndTime, the returned price is the collectionMintCost instead of collectionEndMintCost because the logic go to the else branch. Its an incorrect price because its the price at the beginning of the collection. As you can see on mint(), a user can mint a token on the block.timestamp publicEndTime.
Users that mint on the last block.timstamp mint at an unexpected price and for all the minting methods which use the getPrice() function.
You can see the logs of the test with this image:
Note: to view the image, please see the original submission here.
Heres the gist if you want to execute the PoC directly.
You can execute the test with this command:
Change the < & > to <= & => on the else/if branch inside the getPrice() function.
Invalid Validation
a2rocket (NextGen) confirmed via duplicate issue #1391
0xsomeone (judge) commented:
