You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
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
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.
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
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.
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.
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.
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.
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.
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.
Index
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
The text was updated successfully, but these errors were encountered: