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: 37/93
Findings: 3
Award: $94.47
🌟 Selected for report: 0
🚀 Solo Findings: 0
48.5872 USDC - $48.59
Judge has assessed an item in Issue #153 as Medium risk. The relevant finding follows:
send()
In ForgottenRunesWarriorsGuild.withdrawAll.
transfer()
and send()
should be avoided because they take a hard dependency on gas costs by forwarding a fixed amount of gas: 2300. Gas costs of opcodes can change thus the fallback function can change to consume more than 2300 gas, hence transfer()
and send()
would fail.
(bool success, ) = payable(msg.sender).call{value:address(this).balance)}(""); require(success, "Transfer failed");
#0 - gzeoneth
2022-06-18T19:19:14Z
Duplicate of #254
🌟 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
require
statementsSome require
statements in this contract are missing an error message. One should be added.
ForgottenRunesWarriorsMinter.forwardERC20s ForgottenRunesWarriorsMinter.withdraw ForgottenRunesWarriorsMinter.withdrawAll
instead of checking mintlistMinted[msg.sender] == false
, check !mintlistMinted[msg.sender]
in
mintlistSummon
claimSummon
ForgottenRunesWarriorsGuild._baseURI (contracts/ForgottenRunesWarriorsGuild.sol#76-78) is never used and should be removed
the phase time should include the start time (also inclusive comparison saves gas)
ForgottenRunesWarriorsMinter.daStarted() ForgottenRunesWarriorsMinter.mintlistStarted() ForgottenRunesWarriorsMinter.publicStarted() ForgottenRunesWarriorsMinter.claimsStarted() ForgottenRunesWarriorsMinter.selfRefundsStarted() ForgottenRunesWarriorsGuild.withdrawAll() ForgottenRunesWarriorsGuild.forwardERC20s()
For example:
block.timestamp > daStartTime
-> block.timestamp >= daStartTime
token.transfer(msg.sender, amount)
require(address(msg.sender) != address(0)); token.transfer(msg.sender, amount);
although there is no serious vulnerability here, the return value should be checked by wrapping the transfer
with require
so the transaction will revert if the token transfer was not successful.
require(token.transfer(msg.sender, amount), "transfer failed")
send()
In ForgottenRunesWarriorsGuild.withdrawAll.
transfer()
and send()
should be avoided because they take a hard dependency on gas costs by forwarding a fixed amount of gas: 2300. Gas costs of opcodes can change thus the fallback function can change to consume more than 2300 gas, hence transfer()
and send()
would fail.
(bool success, ) = payable(msg.sender).call{value:address(this).balance)}(""); require(success, "Transfer failed");
🌟 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
i++ is generally more expensive because it must increment a value and return the old value, so it may require holding two numbers in memory. ++i only uses one number in memory.
Example:
for (uint256 i = startIdx; i < endIdx + 1; i++) -> for (uint256 i = startIdx; i < endIdx + 1; ++i)
If a variable is not initialized it is automatically set to the default value (0 for uint, false for bool, address(0) for address...). Explicitly initializing it with its default value is an anti-pattern and wastes gas.
Example:
uint256 i = 0
-> uint256 i
external
public functions that are never called by the contract should be declared external to save gas.
for example ForgottenRunesWarriorsGuild.tokenURI