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 #318

Open
code423n4 opened this issue Aug 6, 2022 · 0 comments
Open

Gas Optimizations #318

code423n4 opened this issue Aug 6, 2022 · 0 comments
Labels

Comments

@code423n4
Copy link
Contributor

[G-01] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead

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.

https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Use a larger size then downcast where needed.

There are 2 instances of this issue:

DebtToken.sol#L16

Disputes.sol#L100

[G-02] Use custom error rather than revert()/require() strings to save deployment gas

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

There are 63 instances of this issue:

DebtToken.sol#L33

DebtToken.sol#L50

DebtToken.sol#L96

DebtToken.sol#L104

ProjectFactory.sol#L36

HomeFiProxy.sol#L41

HomeFiProxy.sol#L81

HomeFiProxy.sol#L105

HomeFiProxy.sol#L133

HomeFi.sol#L73

HomeFi.sol#L78

HomeFi.sol#L84

HomeFi.sol#L142

HomeFi.sol#L191

HomeFi.sol#L255

Disputes.sol#L64

Disputes.sol#L106

Disputes.sol#L183

25 instances here

Project.sol

20 instances here

Community.sol

[G-03] Duplicated require() / revert() checks should be refactored to a modifier or function

Saves deployment costs.

There is 1 instance of this issue:

DebtToken.sol#L96

DebtToken.sol#L104

[G-04] Using calldata instead of memory for read-only arguments in external function saves gas

There are 4 instances of this issue:

DebtToken.sol#L45-L46

HomeFi.sol#L210

Community.sol#L489

[G-05] State variables only set in the constructor should be declared immutable

Avoids a Gsset (20000 gas) in the constructor, and replaces each Gwarmacces (100 gas) with a PUSH32 (3 gas).

There are 17 instances of this issue:

ProjectFactory.sol#L28

HomeFiProxy.sol#L20

Disputes.sol#L27

HomeFi.sol#L38-L42

HomeFi.sol#L54-L56

Project.sol#L40

Project.sol#L52-L58

Community.sol#L33-L35

Community.sol#L48

[G-06] No need to explicitly initialize variables with default values

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.

As an example: for (uint256 i = 0; i < numIterations; ++i) { should be replaced with for (uint256 i; i < numIterations; ++i) {

There are 6 instances of this issue:

HomeFiProxy.sol#L87

Project.sol#L248

Project.sol#L311

Project.sol#L322

Project.sol#L412

Community.sol#L624

[G-07] ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)

Saves 6 gas per loop.

There are 9 instances of this issue:

HomeFiProxy.sol#L87

Project.sol#L248

Project.sol#L311

Project.sol#L322

Project.sol#L368

Project.sol#L603

Project.sol#L650

Project.sol#L710

Community.sol#L624

[G-08] Increments can be unchecked

In Solidity 0.8+, there’s a default overflow check on unsigned integers. It’s possible to uncheck this in for-loops and save some gas at each iteration, but at the cost of some code readability, as this uncheck cannot be made inline.

ethereum/solidity#10695

There are 9 instances of this issue:

HomeFiProxy.sol#L87

Project.sol#L248

Project.sol#L311

Project.sol#L322

Project.sol#L368

Project.sol#L603

Project.sol#L650

Project.sol#L710

Community.sol#L624

[G-09] Functions guaranteed to revert when called normal users can be marked payable

If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided.

There are 18 instances of this issue:

HomeFiProxy.sol#L102

HomeFiProxy.sol#L128

HomeFiProxy.sol#L152

HomeFi.sol#L123

HomeFi.sol#L157

HomeFi.sol#L171

HomeFi.sol#L185

HomeFi.sol#L200

Disputes.sol#L145

Disputes.sol#L84-L88

Community.sol#L555

Community.sol#L566

Community.sol#L577

Community.sol#L592

Community.sol#L290

Community.sol#L303

Community.sol#L340

Community.sol#L465

[G-10] Not using the named return variables when a function returns, wastes deployment gas

There is 1 instance of this issue:

HomeFi.sol#L307

[G-11] Splitting require() statements that use && saves gas

See this issue which describes the fact that there is a larger deployment gas cost, but with enough runtime calls, the change ends up being cheaper

There are 5 instances of this issue:

Disputes.sol#L61-L65

Disputes.sol#L106-L109

Project.sol#L195

Community.sol#L353-L357

[G-12] internal functions only called once can be inlined to save gas

Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.

There are 2 instances of this issue:

HomeFi.sol#L284-L297

Disputes.sol#L207-L223

[G-13] public functions to external

The following functions could be set external to save gas and improve code quality. External call cost is less expensive than of public functions.

There are 2 instances of this issue:

HomeFi.sol#L265

Project.sol#L726

[G-14] x = x + y is cheaper than x += y

There are 4 instances of this issue:

HomeFi.sol#L289

Project.sol#L772

Community.sol#L423

Community.sol#L435

[G-15] Using bools for storage incurs overhead

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/58f635312aa21f947cae5f8578638a85aa2519f5/contracts/security/ReentrancyGuard.sol#L23-L27 Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD, and to avoid Gsset (20000 gas) when changing from false to true, after having been true in the past

There are 4 instances of this issue:

HomeFi.sol#L50

Project.sol#L68

Project.sol#L78

Community.sol#L55

[G-16] Using > 0 costs more gas than != 0 when used in a require() statement

This change saves 6 gas per instance.

There are 2 instances of this issue:

Disputes.sol#L107

Community.sol#L764

[G-17] Using private rather than public for constants, saves gas

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

There is 1 instance of this issue:

Project.sol#L60

[G-18] <array>.length should not be looked up in every loop of a for-loop

The overheads outlined below are PER LOOP, excluding the first loop

  • storage arrays incur a Gwarmaccess (100 gas)
  • memory arrays use MLOAD (3 gas)
  • calldata arrays use CALLDATALOAD (3 gas)

Caching the length changes each of these to a DUP<N> (3 gas), and gets rid of the extra DUP<N> needed to store the stack offset

There is 1 instance of this issue:

Project.sol#L603

@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
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