Forgotten Runes Warrior Guild contest - Hawkeye's results

16,000 Warrior NFTs sold in a phased Dutch Auction.

General Information

Platform: Code4rena

Start Date: 03/05/2022

Pot Size: $30,000 USDC

Total HM: 6

Participants: 93

Period: 3 days

Judge: gzeon

Id: 118

League: ETH

Forgotten Runes

Findings Distribution

Researcher Performance

Rank: 74/93

Findings: 2

Award: $45.73

🌟 Selected for report: 0

🚀 Solo Findings: 0

QA report

I. Redundant address (0) check. The call to _mint() will guarantee that the recipient is not set to that.

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L258

II. For better readability, use ++ instead of +=1

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L248

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L193

III.Use enumerable set from OZ contracts to deal with the issue of duplicates when adding to daMinters[ ] in BidSummon(), this will prevent checking for the same address when calculating the refund in issueRefund() for the specific address (in the event, there are duplicates) and saving needed gas.

PS. This is a cross-over between a recommendation and also gas optimisation.

IV. Variables are already the default, no need to assign them :

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L162

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L220

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L259

V. Owner can deny users a refund in the worst case

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L157

If the auction is not sold out, it is the owner who sets the final price and it can be too high for the calculation of totalCostOfMints in refundOwed(), thereby reverting. Since each user’s daAmountPaid would be different, it's highly unlikely that the finalPrice will be favourably set to initiate a refund.

PS. It was only after continuously asking for clarification(relating to a solution to prevent users from not getting a refund if it is set at an unreasonable price) that the dev(#dotta) mentioned :

“If the auction doesn't sell out, i'll update the price to reflect 0.6”

The comments in SetFinalPrice() does not state this:

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L577

Add : require(new Price ≤lowestPrice, “too high”) within setFinalPrice().

Gas

I. Since the state variable is already cached, no need to write to it again.

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsGuild.sol#L102

Use uint256 tokenId=numMinted++ and remove line 104.

II. daStarted() ensures that block.timestamp >daStartTime. Therefore, use unchecked block to save gas.

https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L287

III. Since the stepDeduction is being checked:

https://github.com/code-423n4/2022-05-runes/blob/main/contracts/ForgottenRunesWarriorsMinter.sol#L292-L293

On line 295, the currentPrice will only be returned when the stepDeduction < startPrice. Therefore, use unchecked block for the calculation of currentPrice.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter