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: 35/133
Findings: 2
Award: $194.90
🌟 Selected for report: 0
🚀 Solo Findings: 0
In the main rigor flow, There is a control point Note that you cannot submit a project with no total budget. Therefore it requires at least one task with a budget > 0.
in From project creation to community lending to the project
.
From project creation to community lending to the project
- Builder publishes his project to the community. It requires signing data that includes community ID, APR, publishing fee and nonce . Both builder and community owner have to sign the data. The signatures and data are used to call
publishProject(bytes _data, bytes _signature)
. Note that you cannot submit a project with no total budget. Therefore it requires at least one task with a budget > 0.
However, the code to implement this control points is not found in the function publishProject(bytes _data, bytes _signature)
This will invalidate the control point and potentially allow projects with no total budget to be published under some conditions.
/// @inheritdoc ICommunity function publishProject(bytes calldata _data, bytes calldata _signature) external virtual override whenNotPaused { // Compute hash from bytes bytes32 _hash = keccak256(_data); // Decode params from _data ( uint256 _communityID, address _project, uint256 _apr, uint256 _publishFee, uint256 _publishNonce, bytes memory _messageHash ) = abi.decode( _data, (uint256, address, uint256, uint256, uint256, bytes) ); // Local instance of community and community project details. For saving gas. CommunityStruct storage _community = _communities[_communityID]; ProjectDetails storage _communityProject = _community.projectDetails[ _project ]; // Revert if decoded nonce is incorrect. This indicates wrong _data. require( _publishNonce == _community.publishNonce, "Community::invalid publishNonce" ); // Reverts if _project not originated from HomeFi require(homeFi.isProjectExist(_project), "Community::Project !Exists"); // Local instance of variables. For saving gas. IProject _projectInstance = IProject(_project); address _builder = _projectInstance.builder(); // Revert if project builder is not community member require(_community.isMember[_builder], "Community::!Member"); // Revert if project currency does not match community currency require( _projectInstance.currency() == _community.currency, "Community::!Currency" ); // check signatures checkSignatureValidity(_community.owner, _hash, _signature, 0); // must be community owner checkSignatureValidity(_builder, _hash, _signature, 1); // must be project builder // If already published then unpublish first if (projectPublished[_project] > 0) { _unpublishProject(_project); } // Store updated details _community.publishNonce = ++_community.publishNonce; _communityProject.apr = _apr; _communityProject.publishFee = _publishFee; projectPublished[_project] = _communityID; // If _publishFee is zero than mark publish fee as paid if (_publishFee == 0) _communityProject.publishFeePaid = true; emit ProjectPublished( _communityID, _project, _apr, _publishFee, _communityProject.publishFeePaid, _messageHash ); }
Add code like the following to the function publishProject(bytes _data, bytes _signature)
// Revert if no total budget. require(_total_budget > 0, "Project::!value>0");
#0 - parv3213
2022-08-17T06:45:51Z
🌟 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
Low Risk Issues
Issue | Instances | |
---|---|---|
1 | Too many similar modifier | 6 |
Total: 6 instances over 1 issues
1. Too many similar modifier
There are 5 same functional noZero
modifiers in five contracts( HomeFiProxy.sol
, HomeFi.sol
, ProjectFactory.sol
, DebtToken.sol
, Disputes.sol
, Community.sol
). Then there are two places in the project.sol
where the noZero address
is determined, but the modifier
is not used.
With so many duplicate codes spread across different codes, this brings a potential risk for the contract. For example, instance # 5 is missing a comment compared to the other 4 codes. Although this comment does not affect the contract, it poses a high-level risk if you will change the business logic in the future.
There are 6 instances of this issue:
File: contracts/HomeFi.sol #1 77: modifier nonZero(address _address) { 78: require(_address != address(0), "HomeFi::0 address"); 79: _; 80: }
File: contracts/ProjectFactory.sol #2 34: modifier nonZero(address _address) { 35: // Ensure an address is not the zero address (0x00) 36: require(_address != address(0), "PF::0 address"); 37: _; 38: }
File: contracts/Disputes.sol #3 37: modifier nonZero(address _address) { 38: // Ensure an address is not the zero address (0x00) 39: require(_address != address(0), "Disputes::0 address"); 40: _; 41: }
File: contracts/Community.sol #4 67: modifier nonZero(address _address) { 68: // Ensure an address is not the zero address (0x00) 69: require(_address != address(0), "Community::0 address"); 70: _; 71: }
File: contracts/HomeFiProxy.sol #5 40: modifier nonZero(address _address) { 41: require(_address != address(0), "Proxy::0 address"); 42: _; 43: }
The noZero address
is determined, but the modifier
is not used.
File: contracts/Project.sol #6 L135: require(_contractor != address(0), "Project::0 address"); L153: require(contractor != address(0), "Project::0 address");