Platform: Code4rena
Start Date: 26/07/2022
Pot Size: $75,000 USDC
Total HM: 29
Participants: 179
Period: 6 days
Judge: LSDan
Total Solo HM: 6
Id: 148
League: ETH
Rank: 117/179
Findings: 3
Award: $56.49
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: cloudjunky
Also found by: 0x1f8b, 0x4non, 0x52, 0xDjango, 0xHarry, 0xNazgul, 0xNineDec, 0xf15ers, 0xsanson, 0xsolstars, 8olidity, Bnke0x0, CertoraInc, Chom, Deivitto, Dravee, GalloDaSballo, GimelSec, IllIllI, Jmaxmanblue, JohnSmith, Jujic, Kenshin, Krow10, Lambda, MEP, Noah3o6, RedOneN, Ruhum, StErMi, StyxRave, TomJ, Treasure-Seeker, TrungOre, _Adam, __141345__, arcoun, asutorufos, bardamu, bearonbike, bin2chen, brgltd, bulej93, c3phas, cRat1st0s, carlitox477, cccz, codexploder, cryptonue, cryptphi, cthulhu_cult, dharma09, dipp, djxploit, durianSausage, ellahi, giovannidisiena, hansfriese, horsefacts, hyh, immeas, indijanc, jayjonah8, jayphbee, joestakey, kenzo, kyteg, ladboy233, minhquanym, navinavu, obront, oyc_109, peritoflores, rbserver, reassor, rokinot, rotcivegaf, saian, scaraven, shenwilly, simon135, sseefried, teddav, zzzitron
0.0037 USDC - $0.00
Using payable(address).transfer
has been deprecated in favor of using .call{value:...}("")
as the proper way of sending ETH. Using transfer
or send
will make transactions fail when the address corresponds to a contract that does not implement a payable function using less than 2300 gas (e.g. some multisigs or proxied contracts). As gas costs can change over time and smart contracts are increasingly used as investment aggregators / fund managers over EOAs, it's recommended to stop using transfer
altogether.
In the specific context of this project, current implementation will prevent such contracts from being able to correctly interact with the core functionality of this protocol, as the payEther
function is used for all ETH transfers when filling orders and settling balances.
#0 - KenzoAgada
2022-08-03T14:02:27Z
Duplicate of #343
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x4non, 0x52, 0xA5DF, 0xDjango, 0xLovesleep, 0xNazgul, 0xNineDec, 0xSmartContract, 0xackermann, 0xc0ffEE, 0xf15ers, 0xmatt, 0xsanson, 0xsolstars, 8olidity, AuditsAreUS, Bahurum, Bnke0x0, CRYP70, CertoraInc, Ch_301, Chom, CryptoMartian, Deivitto, DevABDee, Dravee, ElKu, Franfran, Funen, GalloDaSballo, GimelSec, GiveMeTestEther, Green, JC, Jmaxmanblue, JohnSmith, Jujic, Junnon, Kenshin, Krow10, Kumpa, Lambda, MEP, Maxime, MiloTruck, Mohandes, NoamYakov, Picodes, RedOneN, Rohan16, Rolezn, Ruhum, RustyRabbit, Sm4rty, Soosh, StErMi, StyxRave, Tadashi, TomJ, Treasure-Seeker, TrungOre, Waze, _Adam, __141345__, ajtra, ak1, apostle0x01, arcoun, asutorufos, async, benbaessler, berndartmueller, bin2chen, brgltd, c3phas, cRat1st0s, carlitox477, chatch, codetilda, codexploder, cryptonue, cryptphi, csanuragjain, cthulhu_cult, delfin454000, dipp, dirk_y, djxploit, ellahi, exd0tpy, fatherOfBlocks, giovannidisiena, hansfriese, horsefacts, hyh, idkwhatimdoing, indijanc, jayfromthe13th, jayphbee, joestakey, kenzo, kyteg, lucacez, luckypanda, mics, minhquanym, obront, oyc_109, pedr02b2, rajatbeladiya, rbserver, reassor, robee, rokinot, rotcivegaf, sach1r0, saian, saneryee, sashik_eth, scaraven, shenwilly, simon135, sseefried, supernova, teddav, ych18, zuhaibmohd, zzzitron
35.1687 USDC - $35.17
Domain specific require
statements with no messages - functions that comprise the core functionality of the protocol and are intended to be used by a third party should probably give meaningful error messages in their require
statements. fillAsk
falls more or less in line with this, but fillBid
and fillCriteriaBid
seem to be missing some additional information.
Variable declarations shadowing inherited variable / function - Functions in VoteEscrowDelegation.sol
name variables or input arguments as tokenId
and checkpoint
. Both names are already being used by a state variable and a function declared in VoteEscrowCore.sol
. It has no practical impact as local variables take precedence in each scope, but this should be avoided to prevent confusion when developing (same name+type variables with vastly different semantics as is the case with tokenId
may throw anyone off when reading code).
Missing event
emission for critical updates and core functionality - traderClaim
, exchangeClaim
and multiStakerClaim
should probably emit events for easier off-chain monitoring. Additionally, modifying critical parameters and addresses of contracts should always emit events signaling each modification (e.g. both preparing and setting the corresponding Distributor or adding vote escrow / changing Trader) for both transparency and auditing concerns.
Copypasted docstring fail - traderRewards
mentions a returned tuple which is not there and exchangeRewards
describes trader rewards. Should probably revisit documentation of external functions intended for third-party integration / use.
Extract inlined constant maxSupply
to an explicit contract constant
🌟 Selected for report: JohnSmith
Also found by: 0x1f8b, 0xA5DF, 0xDjango, 0xKitsune, 0xLovesleep, 0xNazgul, 0xSmartContract, 0xmatt, 0xsam, Aymen0909, Bnke0x0, CRYP70, Chandr, Chinmay, CodingNameKiki, Deivitto, Dravee, ElKu, Fitraldys, Funen, GalloDaSballo, Green, IllIllI, JC, Jmaxmanblue, Junnon, Kaiziron, Kenshin, Krow10, Maxime, Migue, MiloTruck, Noah3o6, NoamYakov, Randyyy, RedOneN, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, StyxRave, TomJ, Tomio, _Adam, __141345__, ajtra, ak1, apostle0x01, asutorufos, async, benbaessler, brgltd, c3phas, cRat1st0s, carlitox477, delfin454000, djxploit, durianSausage, ellahi, erictee, fatherOfBlocks, gerdusx, gogo, hyh, jayfromthe13th, jayphbee, joestakey, kaden, kenzo, kyteg, ladboy233, lucacez, m_Rassska, mics, minhquanym, oyc_109, pfapostol, rbserver, reassor, rfa, robee, rokinot, sach1r0, saian, samruna, sashik_eth, simon135, supernova, tofunmi, zuhaibmohd
21.3211 USDC - $21.32
Loops - general improvements for all loops in scope: GolomTrader.sol
: 1, VoteEscrowDelegation.sol
: 2, 3, 4, RewardDistributor.sol
: 5, 6, 7, 8, 9, 10, 11.
for (...; i < arr.length; ...) { ... }
with uint cachedLength = arr.length; for (...; i < cachedLength; ...) { ... }
.epoch
access in traderClaim
, exchangeClaim
and multiStakerClaim
. e.g. uint currentEpoch = epoch; for ...
claimed[i]
access in stakerRewards
and tokenids[tindex] & epochs[index]
in multiStakerClaim
.++i
for increments if the resulting value is not immediately needed. It costs less gas compared to i++
or i+=1
- as no temporary variable needs to exist in order to return the unincremented value.for (...; ... ; ++i) { ... }
with for (...; ...; ) { ... unchecked { ++i; } }
Cache non constant nor immutable storage variables when reading them multiple times - epoch
in addFee
can be cached to a stack variable uint _epoch = epoch
. Same applies to contract addresses such as ve
, rewardToken
or weth
if they are not made immutable or constant.
Variables that could be made constant / immutable - reducing mutability saves gas on access. Multichain deployment with different addresses for depended on contracts can be handled in the deployment phase instead of the constructor.
Redudant state var initialization of epoch = 0
- default value on construction is already 0.
Use less than 32 characters for require
messages unless necessary - storage is partitioned in 32 bytes slots, each additional slot needed will increase gas on deployment and require an additional read each time is accessed. 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11.
Try to move expensive storage access after possible reverts - e.g. in fillCriteriaBid
proof verification