Platform: Code4rena
Start Date: 01/08/2022
Pot Size: $50,000 USDC
Total HM: 26
Participants: 133
Period: 5 days
Judge: Jack the Pug
Total Solo HM: 6
Id: 151
League: ETH
Rank: 71/133
Findings: 2
Award: $62.38
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Lambda
Also found by: 0x1f8b, 0x52, 0xA5DF, 0xNazgul, 0xNineDec, 0xSmartContract, 0xSolus, 0xf15ers, 0xkatana, 0xsolstars, 8olidity, Aymen0909, Bahurum, Bnke0x0, CertoraInc, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, Extropy, Funen, GalloDaSballo, Guardian, IllIllI, JC, Jujic, MEP, Noah3o6, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, SooYa, Soosh, Throne6g, TomJ, Tomio, TrungOre, Waze, Yiko, _Adam, __141345__, a12jmx, ajtra, ak1, arcoun, asutorufos, ayeslick, benbaessler, berndartmueller, bin2chen, bobirichman, brgltd, bulej93, byndooa, c3phas, codexploder, cryptonue, cryptphi, defsec, delfin454000, dipp, djxploit, erictee, exd0tpy, fatherOfBlocks, gogo, hake, hansfriese, horsefacts, hyh, ignacio, indijanc, joestakey, kaden, mics, minhquanym, neumo, obront, oyc_109, p_crypt0, pfapostol, poirots, rbserver, robee, rokinot, rotcivegaf, sach1r0, saian, samruna, saneryee, scaraven, sikorico, simon135, sseefried, supernova
40.621 USDC - $40.62
/// @notice bytes2 array of upgradable contracts initials
Change contracts
to contract
/// @dev mapping that tell if a particular address is active(latest version of contract)
Change tell
to tells
or shows
/// @dev mapping that maps contract initials with there implementation address
Change there
to their
// Revert if project not originated of HomeFi
Change of
to by
// Revert is signer is not builder, contractor or subcontractor.
Change first instance of is
to if
lenderFee = _lenderFee; // the percentage must be multiplied with 10
Change with
to by
// Allocate funds to tasks and mark then as allocated
Change then
to them
or else remove then
// As as needs to go though funding process again.
Replace repeated word as
The same typo (Revet
) occurs in both lines referenced below:
Example (Project.sol: L514):
// Revet if sender is not builder or contractor
Change Revet
to Revert
in both cases
// Max amount out times this loop will run
Change out
to of
// This is to ensure the transaction do not run out of gas (max gas limit)
Change do
to does
The same typo (is
) occurs in both lines referenced below:
// If there is enough funds to allocate this task
Change is
to are
in both cases
// Emit event if _hash. This way this hash needs not be stored in memory.
Change needs
to need
// If _publishFee is zero than mark publish fee as paid
Change than
to then
The same typo (address - address
) occurs in both lines referenced below:
Example (Project.sol: L866):
* @param _address address - address checked for validity
Suggestion:
* @param _address address, which is checked for validity
// Initiate empty equal equal to member count length
Remove repeated word equal
Comments should communicate clearly, immediately and without ambiguity. The comments below could be improved, as shown:
// If balance is present then it to the builder.
Suggestion: Change then it
to then transfer it
* @param _communityID uint256 - the the uuid of the community
Suggestion:
* @param _communityID uint256 - the uuid of community the project is held in
In theory, comments over 79 characters should wrap using multi-line comment syntax. Even if somewhat longer comments are acceptable, there are cases where very long comments interfere with readability.
Below are five instances of long comments whose readability could be improved, as shown:
* @notice Initialize all the homeFi contract in the correct sequential order and generate upgradable proxy for them.
Suggestion:
* @notice Initialize all the homeFi contract in the correct sequential order * and generate upgradable proxy for them.
* @param _contractAddresses address array of contract implementation address that needs to be upgraded
Suggestion:
* @param _contractAddresses address array of contract implementation — * address that needs to be upgraded.
* If contractor is assigned but not delegated then only checks for builder and contractor signature.
Suggestion:
* If contractor is assigned but not delegated, then only checks * for builder and contractor signature.
* @dev Check if recovered signatures match with builder, contractor and subcontractor address for a task.
Suggestion:
* @dev Check if recovered signatures match with builder, contractor * and subcontractor address for a task.
* @param pos which signature to read. A prior bounds check of this parameter should be performed, to avoid out of bounds access
Suggestion:
* @param pos which signature to read — a prior bounds check of this parameter should be performed * to avoid out of bounds access.
Terms incorporating "white," "black," "master" or "slave" are potentially problematic. Substituting more neutral terminology is becoming common practice. It is apparent that use of whitelist
has been avoided in Rigor Protocol
. There is one instance of master
, however, as shown below:
/// @dev Added to make sure master implementation cannot be initialized
🌟 Selected for report: c3phas
Also found by: 0x040, 0x1f8b, 0xA5DF, 0xNazgul, 0xSmartContract, 0xSolus, 0xc0ffEE, 0xkatana, 0xsam, 8olidity, Aymen0909, Bnke0x0, CertoraInc, Chinmay, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, Extropy, Fitraldys, Funen, GalloDaSballo, Guardian, IllIllI, JC, Lambda, MEP, Metatron, MiloTruck, Noah3o6, NoamYakov, PaludoX0, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, SooYa, TomJ, Tomio, Waze, _Adam, __141345__, a12jmx, ajtra, ak1, apostle0x01, asutorufos, ballx, benbaessler, bharg4v, bobirichman, brgltd, cryptonue, defsec, delfin454000, dharma09, djxploit, durianSausage, eierina, erictee, fatherOfBlocks, gerdusx, gogo, hake, hyh, ignacio, jag, kaden, kyteg, lucacez, mics, minhquanym, oyc_109, pfapostol, rbserver, ret2basic, robee, rokinot, sach1r0, saian, samruna, scaraven, sikorico, simon135, supernova, teddav, tofunmi, zeesaw
21.7554 USDC - $21.76
require
functionSplitting into separate require()
statements saves gas
require( _disputeID < disputeCount && disputes[_disputeID].status == Status.Active, "Disputes::!Resolvable" );
Recommendation:
require(_disputeID < disputeCount, "Disputes::!Resolvable"); require(disputes[_disputeID].status == Status.Active, "Disputes::!Resolvable");
require( _actionType > 0 && _actionType <= uint8(ActionType.TaskPay), "Disputes::!ActionType" );
Recommendation:
require(_actionType != 0, "Disputes::!ActionType"); require(_actionType <= uint8(ActionType.TaskPay), "Disputes::!ActionType");
require( _lendingNeeded >= _communityProject.totalLent && _lendingNeeded <= IProject(_project).projectCost(), "Community::invalid lending" );
Recommendation:
require(_lendingNeeded >= _communityProject.totalLent, "Community::invalid lending"); require(_lendingNeeded <= IProject(_project).projectCost()), "Community::invalid lending");
!= 0
instead of > 0
in a require
statement if variable is an unsigned integer!= 0
should be used where possible since > 0
costs more gas
require( _actionType > 0 && _actionType <= uint8(ActionType.TaskPay), "Disputes::!ActionType" );
Recommendation: Change _actionType > 0
to _actionType != 0
require(_cost > 0, "Project::!value>0");
Recommendation: Change _cost > 0
to _cost != 0
require(_repayAmount > 0, "Community::!repay");
Recommendation: Change _repayAmount > 0
to _repayAmount != 0
For example, initializing bool
variables to their default value of false
is unnecessary and costs gas
bool _unapproved = false;
Change to bool _unapproved;
for
loopSince calculating the array length costs gas, it's best to read the length of the array from memory before executing the loop
for (uint256 i = 0; i < _communities[_communityID].memberCount; i++) { _members[i] = _communities[_communityID].members[i]; }
Suggestion:
uint256 totalCommunitiesMembers = _communities[_communityID].memberCount; for (uint256 i = 0; i < totalCommunitiesMembers; i++) { _members[i] = _communities[_communityID].members[i]; }
++i
instead of i++
to increase count in a for
loopSince use of i++
(or equivalent counter) costs more gas, it is better to use ++i
for (uint256 i = 0; i < _length; i++) { _generateProxy(allContractNames[i], _implementations[i]); }
Suggestion:
for (uint256 i = 0; i < _length; ++i) { _generateProxy(allContractNames[i], _implementations[i]); }
Similarly for the nine for
loops referenced below:
for
loopUnderflow/overflow checks are made every time i++
(or ++i
or equivalent counter) is called. Such checks are unnecessary since i
is already limited. Therefore, use unchecked{i++}
/unchecked{++i}
instead
for (uint256 i = 0; i < _length; i++) { _generateProxy(allContractNames[i], _implementations[i]); }
Suggestion:
for (uint256 i = 0; i < _length;) { _generateProxy(allContractNames[i], _implementations[i]); unchecked{ ++i; } }
Similarly for the nine for
loops referenced below:
Note that while, for presentation purposes, I have separated the for
loop-related gas savings opportunities above, they should be combined.