Rigor Protocol contest - ajtra's results

Community lending and instant payments for new home construction.

General Information

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

Rigor Protocol

Findings Distribution

Researcher Performance

Rank: 95/133

Findings: 2

Award: $62.34

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Summary

Low

  1. L-1. Pragma directives olders than libraries used.
  2. L-2. Missing zero address validation

Low

1. L-1. Pragma directives olders than libraries used.

Description

The code is using the version 0.8.6 and there are libraries like openzepelling that use a more recent version 0.8.9.

Mitigation

Update the version of solidity to a more recent one at least 0.8.9.

Lines in the code

DebtToken.sol#L3 ProjectFactory.sol#L3 HomeFiProxy.sol#L3 Disputes.sol#L3 HomeFi.sol#L3 Project.sol#L3 Community.sol#L3 SignatureDecoder.sol#L3 Tasks.sol#L3

2. L-2. Missing zero address validation

Description

Detect missing zero address validation

Mitigation

Include check that the address is not zero

Lines in the code

HomeFi.sol#L119 Project.sol#L103

Index

  1. Post-increment/decrement cost more gas then pre-increment/decrement
  2. Array length should not be looked up in every loop of a for-loop
  3. Require instead of &&
  4. Operatos <= or >= cost more gas than operators < or >
  5. != 0 is cheaper than > 0
  6. Variable1 = Variable1 + (-) Variable2 is cheaper in gas cost than variable1 += (-=) variable2.
  7. Use bytes32 instead of string
  8. Use custom errors rather than REVERT()/REQUIRE() strings to save deployment gas
  9. Using private rather than public for constants, saves gas
  10. Usage of uints/ints smaller than 32 Bytes (256 bits) incurs overhead
  11. Use a more recent version of solidity
  12. Using bools for storage incurs overhead
  13. Calldata vs Memory
  14. Cache variables instead of re-reading then from storage.
  15. Variable is just used when a condition it's true.
  16. Unchecked arithmetic when it is not possible for them to overflow
  17. Initialize variables with default values are not needed
  18. Public function that could be declared external
  19. Tight variable packing
  20. Dead code

Details

1. Post-increment/decrement cost more gas then pre-increment/decrement

Description

++var (--var) cost less gas than var++ (var--)

Lines in the code

HomeFiProxy.sol#L87 HomeFiProxy.sol#L136 Disputes.sol#L121 Project.sol#L248 Project.sol#L311 Project.sol#L322 Project.sol#L368 Project.sol#L603 Project.sol#L625 Project.sol#L650 Project.sol#L672 Project.sol#L710 Community.sol#L140 Community.sol#L624 Tasks.sol#L181

2. Array length should not be looked up in every loop of a for-loop

Description

Storage array length checks incur an extra Gwarmaccess (100 gas) per loop. Store the array length in a variable and use it in the for loop helps to save gas.

Lines in the code

Project.sol#L603

3. Require instead of &&

Description

Split of conditions of an require sentence in different requires sentences can save gas

Lines in the code

Disputes.sol#L61 Disputes.sol#L105 Disputes.sol#L106 Community.sol#L352 Community.sol#L353

4. Operatos <= or >= cost more gas than operators < or >

Description

Change all <= / >= operators for < / > and remember to increse / decrese in consecuence to maintain the logic (example, a <= b for a < b + 1)

Lines in the code

Disputes.sol#L107 Project.sol#L200 Project.sol#L368 Project.sol#L438 Project.sol#L608 Project.sol#L614 Project.sol#L650 Project.sol#L655 Project.sol#L661 Project.sol#L710 Community.sol#L354 Community.sol#L355 Community.sol#L401 Community.sol#L792

5. != 0 is cheaper than > 0

Description

Replace all > 0 for != 0 to save gas.

Lines in the code

Disputes.sol#L107 HomeFi.sol#L245 Project.sol#L195 Project.sol#L380 Project.sol#L601 Project.sol#L691 Community.sol#L261 Community.sol#L427 Community.sol#L764 Community.sol#L840

6. Variable1 = Variable1 + (-) Variable2 is cheaper in gas cost than variable1 += (-=) variable2.

Description

Replace all sentences in the following lines to save gas.

Lines in the code

HomeFi.sol#L289 Project.sol#L179 Project.sol#L250 Project.sol#L290 Project.sol#L431 Project.sol#L440 Project.sol#L456 Project.sol#L616 Project.sol#L663 Project.sol#L711 Project.sol#L772 Community.sol#L423 Community.sol#L435 Community.sol#L798 SignatureDecoder.sol#L83

7. Use bytes32 instead of string

Description

Use bytes32 instead of string when it's possible to save some gas. Probably, in the following places, the token's name and symbol is not going to be longer than 32 bytes so it's possible to change it to save some gas.

Lines in the code

DebtToken.sol#L45 DebtToken.sol#L46

8. Use custom errors rather than REVERT()/REQUIRE() strings to save deployment gas

Description

Custom errors are available from solidity version 0.8.4. The instances below match or exceed that version

Lines in the code

DebtToken.sol#L30 DebtToken.sol#L31 DebtToken.sol#L50 DebtToken.sol#L96 DebtToken.sol#L104 ProjectFactory.sol#L36 ProjectFactory.sol#L63 ProjectFactory.sol#L64 ProjectFactory.sol#L84 HomeFiProxy.sol#L41 HomeFiProxy.sol#L81 HomeFiProxy.sol#L105 HomeFiProxy.sol#L133 Disputes.sol#L39 Disputes.sol#L46 Disputes.sol#L52 Disputes.sol#L61 Disputes.sol#L106 Disputes.sol#L183 HomeFi.sol#L73 HomeFi.sol#L78 HomeFi.sol#L84 HomeFi.sol#L142 HomeFi.sol#L191 HomeFi.sol#L255 Project.sol#L123 Project.sol#L132 Project.sol#L135 Project.sol#L150 Project.sol#L153 Project.sol#L176 Project.sol#L189 Project.sol#L195 Project.sol#L199 Project.sol#L238 Project.sol#L241 Project.sol#L245 Project.sol#L277 Project.sol#L301 Project.sol#L308 Project.sol#L341 Project.sol#L369 Project.sol#L406 Project.sol#L511 Project.sol#L515 Project.sol#L521 Project.sol#L530 Project.sol#L753 Project.sol#L886 Project.sol#L906 Community.sol#L69 Community.sol#L75 Community.sol#L81 Community.sol#L90 Community.sol#L131 Community.sol#L159 Community.sol#L191 Community.sol#L235 Community.sol#L241 Community.sol#L248 Community.sol#L251 Community.sol#L312 Community.sol#L347 Community.sol#L353 Community.sol#L384 Community.sol#L400 Community.sol#L491 Community.sol#L536 Community.sol#L539 Community.sol#L557 Community.sol#L568 Community.sol#L764 Community.sol#L792 Community.sol#L886 Tasks.sol#L44 Tasks.sol#L50 Tasks.sol#L56 Tasks.sol#L124

9. Using private rather than public for constants, saves gas

Description

If needed, the value can be read from the verified contract source code. Savings are due to the compiler not having to create non-payable getter functions for deployment calldata, and not adding another entry to the method ID table

Lines in the code

Project.sol#L60 uint256 public constant override VERSION = 25000;

10. Usage of uints/ints smaller than 32 Bytes (256 bits) incurs overhead

Description

When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size. Use a larger size then downcast where needed

Lines in the code

DebtToken.sol#L16 DebtToken.sol#L47 DebtToken.sol#L82 Disputes.sol#L100 Disputes.sol#L107 Project.sol#L507 SignatureDecoder.sol#L29 SignatureDecoder.sol#L65

11. Use a more recent version of solidity

Description

Use a solidity version of at least 0.8.8 to have user defined value types as a major feature, improves overriding interface functions and reading from immutables. Use a solidity version of at least 0.8.9 to have user defined value type with the fix storage layout of user defined value types for underlying types shorter than 32 bytes. Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value Use a solidity version of at least 0.8.11 to have new builtin function abi.encodeCall(functionPointer, (arg1, arg2, ...)) that type-checks the arguments and returns the ABI-encoded function call data. Use a solidity version of at least 0.8.12 to have Yul Optimizer: Remove mstore and sstore operations if the slot already contains the same value. Use a solidity version of at least 0.8.13 to have Allow annotating inline assembly as memory-safe to allow optimizations and stack limit evasion that rely on respecting Solidity's memory model.

Lines in the code

DebtToken.sol#L3 ProjectFactory.sol#L3 HomeFiProxy.sol#L3 Disputes.sol#L3 HomeFi.sol#L3 Project.sol#L3 Community.sol#L3 SignatureDecoder.sol#L3 Tasks.sol#L3

12. Using bools for storage incurs overhead

Description

Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas), and to avoid Gsset (20000 gas) when changing from 'false' to 'true', after having been 'true' in the past

Lines in the code

DebtToken.sol#L95 DebtToken.sol#L103 ProjectFactory.sol#L102 HomeFiProxy.sol#L30 HomeFiProxy.sol#L168 Disputes.sol#L144 Disputes.sol#L180 Disputes.sol#L191 HomeFi.sol#L50 HomeFi.sol#L243 HomeFi.sol#L268 Project.sol#L68 Project.sol#L78 Project.sol#L84 Project.sol#L148 Project.sol#L412 Project.sol#L582 Project.sol#L720 Project.sol#L730 Project.sol#L750 Community.sol#L55 Community.sol#L61 Community.sol#L642 Community.sol#L713 Tasks.sol#L16 Tasks.sol#L178

13. Calldata vs Memory

Description

Use calldata instead of memory in a function parameter when you are only to read the data can save gas by storing it in calldata

Lines in the code

HomeFi.sol#L210

14. Cache variables instead of re-reading then from storage.

Description

The instances below point to the second access of a state variable within a function. Caching will replace each Gwarmaccess (100 gas) with a much cheaper stack read. Less obvious optimizations include having local storage variables of mappings within state variable mappings or mappings within state variable structs, having local storage variables of structs within mappings, or having local caches of state variable contracts/addresses.

Lines in the code

Community.lendToProject accesing to _communities variable Community.sol#L385 Community.sol#L402 Community.sol#L405 Community.sol#L412 Community.sol#L427

Community.members accesing to _communities variable. Community.sol#L620 Community.sol#L624 Community.sol#L625

Community.returnToLender accesing to _communities when can use _communityProject Community.sol#L692

15. Variable is just used when a condition it's true.

Description

The declare of variables are before an if and those variables not used in other places than inside the if. Move the variables inside to save gas when the condition is false.

Lines in the code

Community.claimInterest declare _lender and _communityProject Community.sol#L836 Community.sol#L837

16. Unchecked arithmetic when it is not possible for them to overflow

Description

The default β€œchecked” behavior costs more gas when adding/diving/multiplying, because under-the-hood those checks are implemented as a series of opcodes that, prior to performing the actual arithmetic, check for under/overflow and revert if it is detected. if it can statically be determined there is no possible way for your arithmetic to under/overflow (such as a condition in an if statement), surrounding the arithmetic in an unchecked block will save gas.

For all for-loops in the code it is possible to change as the following example.

for (uint256 i;i < X;){ -- code -- unchecked { ++i; } }

Lines in the code

HomeFiProxy.sol#L87 HomeFiProxy.sol#L136 Project.sol#L248 Project.sol#L311 Project.sol#L322 Project.sol#L368 Project.sol#L603 Project.sol#L650 Project.sol#L710 Community.sol#L624 Tasks.sol#L181

17. Initialize variables with default values are not needed

Description

If a variable is not set/initialized, it is assumed to have 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.

Lines in the code

HomeFiProxy.sol#L87 HomeFiProxy.sol#L136 Project.sol#L248 Project.sol#L311 Project.sol#L322 Community.sol#L624 Tasks.sol#L181

In the following places, require another change to not initialize the variables. Modifify the condition for _taskID < _length + 1 and use inside the loop the variable as _taskID + 1 to access to the array.

Project.sol#L368 Project.sol#L710

18. Public function that could be declared external

Description

public functions that are never called by the contract should be declared external to save gas.

Lines in the code

DebtToken.sol#L82 DebtToken.sol#L91 DebtToken.sol#L100

19. Tight variable packing

Description

Reorder the variables declaration in the code to save gas. It's important than variables are together until full a slot.

Lines in the code

Move contractorDelegated after contractorConfirmed to store in the same slot and save 1 slot. Project.sol#L78 Move restrictedToAdmin after tokenCurrency3 to store in the same slot and save 1 slot. Community.sol#L55

20. Dead code

Description

Dead code is not used in the contract, and make the code's review more difficult and waste gas. Remove unused functions.

Lines in the code

SignatureDecoder.sol#L20 SignatureDecoder.sol#L43 SignatureDecoder.sol#L61 Community.sol#L910 Tasks.sol#L119 Tasks.sol#L138 Tasks.sol#L175 Tasks.sol#L191 Tasks.sol#L106 Tasks.sol#L88 Tasks.sol#L148 Tasks.sol#L160

#0 - jack-the-pug

2022-08-28T09:14:07Z

"20. Dead code" wut?

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax Β© 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter