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
Rank: 17/93
Findings: 4
Award: $589.18
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: throttle
Also found by: 0xDjango, BowTiedWardens, WatchPug, defsec, dipp, fatherOfBlocks, gzeon, hake, reassor, shung, unforgiven
Included below
There are several important setter functions that lack validation on either the value itself or the timing on which the function can be called. It seems that the developer intentionally wrote these contracts with flexibility in mind, so I am submitting all of these findings as a single vulnerability under the umbrella of "functions unsafely lacking validation".
initialize()
function lacks the initializer
keyword.The following initialize function can be called by the owner as many times as desired. This function sets the minter contract that is allowed to call important functions such as mint()
. The owner can accidently or intentionally set this to a contract address that is not the correct minter contract, effectively DOS'ing the minting process.
These setter functions have no validation. Therefore, the phase times can either be set incorrectly (e.g. claim phase before dutch auction) or the time can be updated during the phase to effectively end it.
These functions are set to public though maybe they should be set to internal and called within setPhaseTimes()
as this function contains validation.
Changing these merkle roots can DOS the event, if desired.
Setting these addresses to contracts that don't support the required functions will DOS the event. In the case of the warrior address, setting this to another compliant contract effectively allows the users to mint knockoff NFTs.
If the owner intentionally or accidently passes 0
for these setters, all minting will be DOS'ed.
Manual review.
Add validation for each of these functions. They should be validated both for proper values as well as the time frame that the call is allowed.
#0 - gzeoneth
2022-06-18T18:06:56Z
Duplicate of #27
🌟 Selected for report: Kulk0
Also found by: 0x1f8b, 0xDjango, BowTiedWardens, Dinddle, broccolirob, defsec, dirk_y, hyh, rajatbeladiya, throttle, unforgiven
There are no internal accounting variables keeping track of how many team summons have been performed, nor are there any checks that the team summons are performed after all of the public phases have been completed. This can lead to less than the desired amount of NFTs available to the public.
Manual review.
Add internal account variables to ensure that the number of team summons performed is less than the desired allotment of team summons. If this is not desired in the case that there are more leftover than anticipated, at least add a check that the team summons can not be performed until after the claim phase to ensure that the amount of team summons does not interfere with the number of NFTs that should be available to the public.
#0 - KenzoAgada
2022-06-06T05:39:09Z
Duplicate of #104.
🌟 Selected for report: defsec
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0x52, 0xDjango, 0xf15ers, 0xkatana, 0xliumin, AuditsAreUS, BowTiedWardens, CertoraInc, Cr4ckM3, Funen, GimelSec, Hawkeye, IllIllI, Kulk0, M0ndoHEHE, MaratCerby, Picodes, Ruhum, TerrierLover, TrungOre, VAD37, WatchPug, berndartmueller, broccolirob, catchup, cccz, cryptphi, csanuragjain, delfin454000, dirk_y, eccentricexit, ellahi, fatherOfBlocks, gzeon, hake, hansfriese, hickuphh3, horsefacts, hubble, hyh, ilan, joestakey, kebabsec, kenta, kenzo, leastwood, m9800, marximimus, minhquanym, oyc_109, p4st13r4, pauliax, pedroais, peritoflores, plotchy, rajatbeladiya, reassor, rfa, robee, rotcivegaf, samruna, shenwilly, shung, simon135, sorrynotsorry, sseefried, teddav, throttle, tintin, unforgiven, z3s
30.3871 USDC - $30.39
Overall, the two contracts that make up this codebase perform the necessary functions well but lack checks for most major actions. Several variables are able to be written and re-written at any time which can cause the contracts to stop functioning correctly. This report will not consist of these issues, but instead will highlight low severity issues and general comments to further strengthen the contracts.
There are several checks to determine if the desired phase has started. All of these checks require that block.timestamp > startTime
though the startTime should be included in the check. These should be changed to block.timestamp >= startTime
. For example, if you tell someone that an event starts at 12:00pm, you should allow them to participate at 12:00pm, not 12:01.
It is important to check that the vault address is not set to address(0) to ensure that no funds are lost.
Contracts contain a floating pragma. It is recommended to deploy all contracts with a single, specific compiler version to reduce the risk of compiler-specific bugs and contracts deployed with different versions. In the case of the forked contacts, I recommend deploying with the exact version that the current live versions were deployed with.
The contract is using the correct IWETH interface for depositing WETH, but then uses the IERC20 interface for transferring the WETH. This does not cause any functional or security issues, but since IWETH contains its own transfer function, it would make sense to keep it consistent.
🌟 Selected for report: BowTiedWardens
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xProf, 0xc0ffEE, 0xf15ers, 0xkatana, 0xliumin, ACai, AlleyCat, CertoraInc, Cityscape, Cr4ckM3, DavidGialdi, Dinddle, FSchmoede, Funen, GimelSec, Hawkeye, IllIllI, Kulk0, M0ndoHEHE, MaratCerby, MiloTruck, Picodes, RoiEvenHaim, Tadashi, TerrierLover, TrungOre, VAD37, WatchPug, antonttc, catchup, defsec, delfin454000, dirk_y, eccentricexit, ellahi, fatherOfBlocks, gzeon, hake, hansfriese, hickuphh3, horsefacts, ilan, joestakey, kebabsec, kenta, kenzo, marximimus, minhquanym, noobie, oyc_109, p4st13r4, pauliax, rajatbeladiya, reassor, rfa, robee, rotcivegaf, saian, samruna, shenwilly, shung, simon135, slywaters, sorrynotsorry, throttle, unforgiven, z3s
15.491 USDC - $15.49
Since these functions do not have any references within the codebase, they may be made external. External functions consume roughly half of the gas compared to public.
https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsGuild.sol#L94-L95 https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L371
These for loops can be optimized by incrementing i
within unchecked{}
. The new pattern would be:
for (uint256 i = 0; i < numWarriors;) { _mint(msg.sender); unchecked { ++i; } }
https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L162-L164 https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L220-L222 https://github.com/code-423n4/2022-05-runes/blob/060b4f82b79c8308fe65674a39a07c44fa586cd3/contracts/ForgottenRunesWarriorsMinter.sol#L259-L261
Since the maximum number of warriors to be summoned is 20, this will easily fit within uint8
The value for dropPerStep
does not change. Therefore, this value can be written and read instead of recalculated each time.