Platform: Code4rena
Start Date: 04/05/2022
Pot Size: $50,000 DAI
Total HM: 24
Participants: 71
Period: 5 days
Judge: Justin Goro
Total Solo HM: 14
Id: 119
League: ETH
Rank: 40/71
Findings: 2
Award: $118.80
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: horsefacts
Also found by: 0x1f8b, 0xYamiDancho, 0xf15ers, 0xkatana, ACai, AlleyCat, Bruhhh, Dravee, Funen, GimelSec, Hawkeye, IllIllI, MaratCerby, PPrieditis, Picodes, Ruhum, TerrierLover, VAD37, berndartmueller, csanuragjain, defsec, delfin454000, eccentricexit, ellahi, fatherOfBlocks, gzeon, hansfriese, hickuphh3, hyh, ilan, joestakey, juicy, kebabsec, oyc_109, rajatbeladiya, reassor, rfa, robee, samruna, simon135, sorrynotsorry, throttle
78.8584 DAI - $78.86
the convention should be followed of starting internal function names with a underscore.
change 2 whitespaces to 1.
require(tranche.currentCoins > 0, 'No coins left to withdraw')
->
require(tranche.currentCoins > 0, 'No coins left to withdraw')
should use double quotation consistantly
From the solidity style guide:
Keeping lines under the PEP 8 recommendation to a maximum of 79 (or 99) characters helps > readers easily parse the code.
Recommendation make the function declarations over multiple lines
function name( type param1, type param2, type param3 ) visibilty { body }
endTime > startTime
or else 0 division could occurinitialize
can be called with endTime == startTime
and that will cause a zero division error.
I recommend to require that endTime > startTime
or take care of this case seperately
.transfer
with require
like transferTo()
, also .transfer()
returns bool
which can be true or false. So it is recommended to check that true
is returned before by wrapping transfer with a require
statement.
The price increase values should be checked:
priceIncreaseFactor > priceIncreaseDenominator
, otherwise the price could decrease / constantpriceIncreaseDenominator > 0
, otherwise obviously the denominator is invalid and we'll get division by 0.add the cheks to SpeedBumpPriceGate.addGate
VoterID#L10 contract comment is incomplete.
when setting _globalTaxPerCapita
in the constructor of PermissionlessBasicPoolFactory
there is no check that _globalTaxPerCapita < 1000
as there is in setGlobalTax
. Hence, the initial tax can be more than 100 percent which will break withdraw().
I recommend adding require(newTaxPerCapita < 1000, 'Tax too high');
to the constructor.
#0 - illuzen
2022-05-12T08:50:55Z
all NC valid, all else duplicates
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0xNazgul, 0xYamiDancho, 0xf15ers, 0xkatana, ACai, CertoraInc, Dravee, Funen, GimelSec, Hawkeye, PPrieditis, Picodes, Ruhum, TerrierLover, Tomio, VAD37, Waze, csanuragjain, defsec, delfin454000, eccentricexit, ellahi, fatherOfBlocks, gzeon, hansfriese, horsefacts, ilan, joestakey, juicy, minhquanym, oyc_109, rajatbeladiya, reassor, rfa, robee, samruna, simon135, z3s
39.9359 DAI - $39.94
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 (uint i = 0; i < rewardTokenAddresses.length; i++)
->
for (uint i = 0; i < rewardTokenAddresses.length; ++i)
PermissionlessBasicPoolFactory.addPool#L115
Calling storage/memory variable which does not change, every loop iteration, is a wrong pattern and wastes gas.
Example:
for (uint i = 0; i < rewardTokenAddresses.length; i++)
->
length = rewardTokenAddresses.length for (uint i = 0; i < length; ++i)
PermissionlessBasicPoolFactory.addPool#L115
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:
uint i = 0
-> uint i
PermissionlessBasicPoolFactory.addPool#L115
external
public functions that are never called by the contract should be declared external to save gas.
for example MerkleDropFactory.withdraw
Use calldata instead of memory for external functions where the function argument is read-only. Reading directly from calldata using calldataload instead of going via memory saves the gas from the intermediate memory operations that carry the values.
#0 - illuzen
2022-05-12T08:49:45Z
all duplicates