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 #171
Comments
Agree, will make some improvements here.
Agreed. This is not a gas optimization; however, increases readability and maintainability.
Potentially valid but won't fix. While there may be trivial gas savings here we like the readability and maintainability of this pattern.
Valid but won't fix. While there may be gas savings here we like the readability and maintainability of this pattern. Adding hard-coded hashes makes the code fragile and harder to read.
Potentially valid but won't fix. This is uint32 to allow packing storage for a significant gas savings. Accepting the input as uint256 would incur additional overhead in checking for overflow before saving these values. Other inputs are logically limited to the size exposed, huge values cannot be used. Accepting the input as uint256 would incur additional overhead in checking for overflow before using these values.
Invalid. This optimization technique is no longer applicable with the current version of Solidity.
May be theoretically valid, but won't fix. I tested this: gas-reporter and our gas-stories suite is reporting a small regression using this technique. It also hurts readability a bit so we wouldn't want to include it unless it was a clear win.
Invalid. We tested the recommendation and got the following results:
Invalid. The baseURI cannot be stored in bytes32 because it may be longer than 32 bytes. It's possible this technique could work for name or symbol, however in order to stay flexible in case a creator would like to use a long value here -- we will keep these as strings.
Agree but won't fix at this time. We use these in the market but not in collections. Unfortunately custom errors are still not as good of an experience for users (e.g. on etherscan). We used them in the market originally because we were nearing the max contract size limit and this was a good way to reduce the bytecode. We'll consider this in the future as tooling continues to improve. |
Table of Contents
Use Function Parameter Instead of State Variable
Issue
Using function parameter value instead of SLOAD state variable saves gas.
PoC
Total of 2 issues found.
Use parameter _baseURI of updatePreRevealContent() of NFTDropCollection.sol
Change line 242 from state variable of baseURI to parameter of _baseURI.
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTDropCollection.sol#L242
Use parameter _postRevealBaseURIHash of updatePreRevealContent() of NFTDropCollection.sol
Change line 242 from state variable of postRevealBaseURIHash to parameter of _postRevealBaseURIHash.
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTDropCollection.sol#L242
Mitigation
Change state variable to parameter variable as listed in above PoC.
Duplicate require() Checks Should be a Modifier or a Function
Issue
Since below require checks are used more than once,
I recommend making these to a modifier or a function.
PoC
Total of 1 issue found.
Mitigation
I recommend making duplicate require statement into modifier or a function.
Internal Function Called Only Once Can be Inlined
Issue
Certain function is defined even though it is called only once.
Inline it instead to where it is called to avoid usage of extra gas.
PoC
Total of 3 issues found.
_initializeAdminRole() of AdminRole.sol
Function called only once at line 148 of NFTDropCollection.sol
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/roles/AdminRole.sol#L13
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTDropCollection.sol#L148
_tryUseFETHBalance() of FETHNode.sol
Function called only once at line 204 of NFTDropMarketFixedPriceSale.sol
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/shared/FETHNode.sol#L46
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/nftDropMarket/NFTDropMarketFixedPriceSale.sol#L204
_initializeMinterRole() of MinterRole.sol
Function called only once at line 150 of NFTDropCollection.sol
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/mixins/roles/MinterRole.sol#L26
https://github.com/code-423n4/2022-08-foundation/blob/792e00df429b0df9ee5d909a0a5a6e72bd07cf79/contracts/NFTDropCollection.sol#L150
Mitigation
I recommend to not define above functions and instead inline it at place it is called.
Constant Value of a Call to keccak256() should Use Immutable
Issue
When using constant it is expected that the value should be converted into a constant value at compile time.
However when using a call to keccak256(), the expression is re-calculated each time the constant is referenced.
Resulting in costing about 100 gas more on each access to this constant.
Link for more details: ethereum/solidity#9232
PoC
Total of 2 issues found.
Mitigation
Change the variable from constant to immutable.
Using Elements Smaller than 32 bytes (256 bits) Might Use More Gas
Issue
Since EVM operates on 32 bytes at a time, if the element is smaller than that, the EVM must use more operations
in order to reduce the elements from 32 bytes to specified size.
Reference: https://docs.soliditylang.org/en/v0.8.15/internals/layout_in_storage.html
PoC
Total of 13 issues found.
Mitigation
I suggest using uint256 instead of anything smaller or downcast where needed.
Unnecessary Default Value Initialization
Issue
When variable is not initialized, it will have its default values.
For example, 0 for uint, false for bool and address(0) for address.
Reference: https://docs.soliditylang.org/en/v0.8.15/control-structures.html#scoping-and-declarations
PoC
Total of 5 issues found.
Mitigation
I suggest removing default value initialization.
For example,
Store Array's Length as a Variable
Issue
By storing an array's length as a variable before the for-loop,
can save 3 gas per iteration.
PoC
Total of 4 issues found.
Mitigation
Store array's length as a variable before looping it.
!= 0 costs less gass than > 0
Issue
!= 0 costs less gas when optimizer is enabled and is used for unsigned integers in require statement.
PoC
Total of 3 issues found.
Mitigation
I suggest changing > 0 to != 0
Keep The Revert Strings of Error Messages within 32 Bytes
Issue
Since each storage slot is size of 32 bytes, error messages that is longer than this will need
extra storage slot leading to more gas cost.
PoC
Total of 28 issues found.
Mitigation
Simply keep the error messages within 32 bytes to avoid extra storage slot cost.
Use Custom Errors to Save Gas
Issue
Custom errors from Solidity 0.8.4 are cheaper than revert strings.
Details are explained here: https://blog.soliditylang.org/2021/04/21/custom-errors/
PoC
Total of 28 issues found.
Mitigation
I suggest implementing custom errors to save gas.
The text was updated successfully, but these errors were encountered: