Platform: Code4rena
Start Date: 30/10/2023
Pot Size: $49,250 USDC
Total HM: 14
Participants: 243
Period: 14 days
Judge: 0xsomeone
Id: 302
League: ETH
Rank: 115/243
Findings: 1
Award: $13.39
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: The_Kakers
Also found by: 00xSEV, 0x3b, Arabadzhiev, DeFiHackLabs, Fulum, Madalad, MrPotatoMagic, SpicyMeatball, Tadev, ZanyBonzy, ZdravkoHr, alexfilippov314, audityourcontracts, cheatc0d3, devival, dy, evmboi32, immeas, lsaudit, mrudenko, oakcobalt, oualidpro, pipidu83, r0ck3tz, rishabh, rotcivegaf, tpiliposian, xAriextz
13.3948 USDC - $13.39
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/MinterContract.sol#L170-L177
No check is being performed on the different parameters of a collection
upon creation in the setCollectionPhases
function.
This means collection with wrong parameters can be created and be potentially unusable, polluting the MinterContract
.
For such collections, most of the core functions of the contract would be unusable. However this vulnerability is only marked as MEDIUM as the setCollectionPhases
function can only be called by the collection admin
, who can call it several time and fix the errors.
Let’s have a look at the setCollectionPhases
function below
function setCollectionPhases(uint256 _collectionID, uint _allowlistStartTime, uint _allowlistEndTime, uint _publicStartTime, uint _publicEndTime, bytes32 _merkleRoot) public CollectionAdminRequired(_collectionID, this.setCollectionPhases.selector) { require(setMintingCosts[_collectionID] == true, "Set Minting Costs"); collectionPhases[_collectionID].allowlistStartTime = _allowlistStartTime; collectionPhases[_collectionID].allowlistEndTime = _allowlistEndTime; collectionPhases[_collectionID].merkleRoot = _merkleRoot; collectionPhases[_collectionID].publicStartTime = _publicStartTime; collectionPhases[_collectionID].publicEndTime = _publicEndTime; }
We can imagine a range of scenarios for a caller to create dysfunctional collections, among which:
if _allowlistEndTime < _allowlistStartTime
and _publicEndTime < _publicStartTime
, the functions burnOrSwapExternalToMint
and burnToMint
will always revert.
if _publicEndTime < _allowlistStartTime
and collectionPhases[_collectionId].salesOption == 2)
, the getPrice
function will return a fixed price even though the descending scale is set as exponential
if _allowlistStartTime < collectionPhases[_collectionID].timePeriod
, the mintAndAuction
and the mint
functions will revert if lastMintDate[_collectionID] == 0
as collectionPhases[col].allowlistStartTime - collectionPhases[col].timePeriod
would underflow.
Manual Review / Visual Studio
An easy fix would be to add a list of checks in the setCollectionPhases
function using multiple require
statements as per below.
function setCollectionPhases(uint256 _collectionID, uint _allowlistStartTime, uint _allowlistEndTime, uint _publicStartTime, uint _publicEndTime, bytes32 _merkleRoot) public CollectionAdminRequired(_collectionID, this.setCollectionPhases.selector) { require(setMintingCosts[_collectionID] == true, "Set Minting Costs"); require(_allowlistStartTime < _allowlistEndTime, “start after end”); require(_publicStartTime < _publicEndTime, “start after end”); require(_allowlistEndTime <= _publicStartTime, “allow list should happen prior to public”); require(_allowlistStartTime < collectionPhases[_collectionID].timePeriod, “allow list should be less than period”); collectionPhases[_collectionID].allowlistStartTime = _allowlistStartTime; collectionPhases[_collectionID].allowlistEndTime = _allowlistEndTime; collectionPhases[_collectionID].merkleRoot = _merkleRoot; collectionPhases[_collectionID].publicStartTime = _publicStartTime; collectionPhases[_collectionID].publicEndTime = _publicEndTime; }
This would prevent all the scenarios listed above and ensure the contract does not get polluted with odd collections.
We should also ensure that the setCollectionCosts
function cannot be called again after setting the phases, meaning we should add a require
statement like so require(setMintingCosts[_collectionID] == true, "Set Minting Costs");
in the setCollectionCosts
.
Invalid Validation
#0 - c4-pre-sort
2023-11-17T13:11:58Z
141345 marked the issue as duplicate of #1274
#1 - c4-pre-sort
2023-11-27T10:33:47Z
141345 marked the issue as not a duplicate
#2 - c4-pre-sort
2023-11-27T10:33:59Z
141345 marked the issue as duplicate of #478
#3 - c4-judge
2023-12-01T21:47:00Z
alex-ppg marked the issue as not a duplicate
#4 - c4-judge
2023-12-01T21:47:12Z
alex-ppg marked the issue as duplicate of #2033
#5 - c4-judge
2023-12-04T10:50:00Z
alex-ppg marked the issue as selected for report
#6 - alex-ppg
2023-12-04T10:52:40Z
The Warden has described all potential scenarios that would fail if the time stamps have been misconfigured for a collection and has described it in great detail.
The main issue I observe is that the collection can be simply reconfigured to rectify the issue, meaning that a QA severity is better suited than a Medium severity.
I invite the wardens of this and all duplicate exhibits to elaborate on a potential attack path based on this misconfiguration (i.e. loss of funds, unauthorized access to sale type) to upgrade its severity.
#7 - c4-judge
2023-12-04T10:52:57Z
alex-ppg changed the severity to QA (Quality Assurance)
#8 - c4-judge
2023-12-04T10:53:16Z
alex-ppg marked the issue as grade-a
#9 - c4-judge
2023-12-04T10:53:22Z
alex-ppg marked the issue as grade-b
#10 - c4-judge
2023-12-09T00:48:10Z
alex-ppg marked the issue as not selected for report