Skip to content

Latest commit

 

History

History
231 lines (186 loc) · 19.5 KB

0xackermann-G.md

File metadata and controls

231 lines (186 loc) · 19.5 KB

Gas Optimizations Report

No. Issue
1 Splitting require which contains && saves gas
2 Using uint256 instead of bool in mappings is more gas efficient [146 gas per instance]
3 Use Custom Errors rather than revert() / require() strings to save deployment gas [68 gas per instance]
4 Usage of uint/int smaller than 32 bytes (256 bits) incurs overhead
5 Structs can be packed into fewer storage slots (20k gas)
6 require() or revert() statements that check input arguments should be at the top of the function
7 Multiple address mappings can be combined into a single mapping of an address to a struct, where appropriate

[G-01] Splitting require which contains && saves gas


Description:

Using multiple require instead of operator && can save more gas. When a require statement has 2 or more expressions with &&, separate them into individual expression results in lesser gas.

Lines of Code:


[G-02] Using uint256 instead of bool in mappings is more gas efficient [146 gas per instance]


Description:

OpenZeppelin uint256 and bool comparison:

Booleans are more expensive than uint256 or any type that takes up a full word because each write operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back. This is the compiler's defense against contract upgrades and pointer aliasing, and it cannot be disabled. The values being non-zero value makes deployment a bit more expensive.

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.

Recommendation:

Use uint256(1) and uint256(2) instead of bool.

Lines of Code:


[G-03] Use Custom Errors rather than revert() / require() strings to save deployment gas [68 gas per instance]


Description:

Custom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they’re hitby avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas.

https://blog.soliditylang.org/2021/04/21/custom-errors/

Recommendation:

Use the Custom Errors feature.

Lines of Code:


[G-04] Usage of uint/int 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. Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so.

Recommendation:

Use a larger size then downcast where needed

Lines of Code:


[G-05] Structs can be packed into fewer storage slots (20k gas)


Description:

Each slot saved can avoid an extra Gsset (20000 gas) for the first setting of the struct. Subsequent reads as well as writes have smaller gas savings.

Recommendation:

Reorder the variables in the struct

Lines of Code:


[G-06] require() or revert() statements that check input arguments should be at the top of the function


Description:

Checks that involve constants should come before checks that involve state variables, function calls, and calculations. By doing these checks first, the function is able to revert before wasting a Gcoldsload (2100 gas) in a function that may ultimately revert in the unhappy case.

Lines of Code:


[G-07] Multiple address mappings can be combined into a single mapping of an address to a struct, where appropriate


Description:

Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot

Lines of Code: