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: 37/71
Findings: 2
Award: $123.79
🌟 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
80.7003 DAI - $80.70
In the contract FixedPricePassThruGate
, The method addGate must return the gateId
in order to avoid user errors, otherwise it's hard to get the added gateId
if in the same block was added more than one.
In the following contracts the methods addPool
, addMerkleTree
, addGate
and addMerkleRoot
must return the createdId
in order to avoid user errors, otherwise it's hard to get the added createdId
if in the same block was added more than one:
transfer
without checking the boolean result, ERC20 standard specify that the token can return false if this call was not made, so it's mandatory to check the result of these methods.It's possible to create a pool with empty rewardTokenAddresses
, fundPool
will be automatic, getRewards
will be empty too. So deposit and withdraw will be free of taxes.
Typo: reaffirm
at VoterID.sol#L231
#0 - illuzen
2022-05-10T06:53:12Z
Valid: 1, 2 Invalid: 4 (see https://github.com/code-423n4/2022-05-factorydao/blob/e22a562c01c533b8765229387894cc0cb9bed116/contracts/MerkleIdentity.sol#L121) Invalid: 6 (empty reward token array means no rewards, so why would someone stake?) Invalid: 7 (https://www.merriam-webster.com/dictionary/reaffirm) Out of scope: 3 (incorrect argument entry is not in scope) Duplicate: 5
#1 - gititGoro
2022-06-05T10:03:51Z
5 should be reported as an exploit risk but it also constitutes a strong QA so I'm leaving it in here.
As for number 3, I'd argue that constructor QA such as input validation is almost always out of scope. For wardens, remember to place yourself in the shoes of the developers when identifying issues. A failed contract deployment affects no one but the person deploying. It's not much more than an inconvenience. If the person deploying fails to notice invalid values, the problem is with process, not programming. 3,4,6 and 7 are invalid.
#2 - 0x1f8b
2022-06-24T16:02:13Z
5 should be reported as an exploit risk but it also constitutes a strong QA so I'm leaving it in here.
As for number 3, I'd argue that constructor QA such as input validation is almost always out of scope. For wardens, remember to place yourself in the shoes of the developers when identifying issues. A failed contract deployment affects no one but the person deploying. It's not much more than an inconvenience. If the person deploying fails to notice invalid values, the problem is with process, not programming. 3,4,6 and 7 are invalid.
5 is the same as https://github.com/code-423n4/2022-05-factorydao-findings/issues/130 and always was sent as Low/QA @gititGoro
🌟 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
43.0933 DAI - $43.09
In the contract FixedPricePassThruGate
, move the check of the msg.value>0 from line 51 to the addGate
method, if is not possible to create a gate for _ethCost=0
this line could be removed because it's checked on line 48
There are require
messages bigger than 32 bytes. More than 32 bytes for message will incur an extra gas costs.
timesWithdrawn
if it was moved to the Gate
structstruct Gate { bytes32 root; // merkle root of whitelist uint maxWithdrawalsAddress; // maximum amount of withdrawals per address uint maxWithdrawalsTotal; // maximum total withdrawals allowed, summed across all addresses uint totalWithdrawals; // number of withdrawals already made mapping(address => uint) timesWithdrawn; }
Remove destination
argument because is forced to be the same as sender from MerkleResistor.sol#L134
Change the incremental logic from i++
to ++i
in order to save some opcodes:
immutable
keyword for the following variables:#0 - illuzen
2022-05-10T06:57:46Z
Valid: 1, 3, 4, 6 Duplicate: 2, 5