Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas Optimizations #342

Open
code423n4 opened this issue Aug 6, 2022 · 1 comment
Open

Gas Optimizations #342

code423n4 opened this issue Aug 6, 2022 · 1 comment
Labels

Comments

@code423n4
Copy link
Contributor

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

@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels Aug 6, 2022
code423n4 added a commit that referenced this issue Aug 6, 2022
@jack-the-pug
Copy link
Collaborator

"20. Dead code" wut?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants