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

Open
code423n4 opened this issue Sep 25, 2022 · 0 comments
Open

Gas Optimizations #241

code423n4 opened this issue Sep 25, 2022 · 0 comments
Labels
bug Something isn't working G (Gas Optimization)

Comments

@code423n4
Copy link
Contributor

code423n4 commented Sep 25, 2022

[G-01] USE CUSTOM ERRORS INSTEAD OF REVERT STRINGS TO SAVE GAS

Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. You could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.
Source: https://blog.soliditylang.org/2021/04/21/custom-errors/

Additional recommendation:
We can add natspec documentation to explain the custom errors in contract.

Instances:
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L87-L88
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L122
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L126
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L171
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L193
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L200
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L41
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L46
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L66
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L68
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L77-L78
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L95
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L46
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L137
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L182
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L203

[G-02] USING UNCHECKED FOR INCREMENTS TO SAVE GAS

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.
Source: ethereum/solidity#10695

Instances
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L63
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L84
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L114
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L84

Sample affected code at file OperatorRegistry.sol#L63:

for (uint256 i = 0; i < arrayLength; ++i) {
addValidator(validatorArray[i]);
}
}

can be changed to the following:

for (uint256 i; i < arrayLength;) {
addValidator(validatorArray[i]);
unchecked {
++i;
}
}

Note: the default value of uint256 i is zero, so no need to assign again to save gas.

[G-03] IT COSTS MORE GAS TO INITIALIZE VARIABLES WITH THEIR DEFAULT VALUE THAN LETTING THE DEFAULT VALUE BE APPLIED

In Solidity, all variables are set to zeros by default. So, do not explicitly initialize a variable with its default value if it is zero.
As an example: for (uint256 i = 0; i < numIterations; ++i) { should be replaced with for (uint256 i; i < numIterations; ++i) {

Instances:
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L63-L64
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L94
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L129
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L84
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L63
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L84
https://github.com/code-423n4/2022-09-frax/blob/main/src/OperatorRegistry.sol#L114

[G-04] ++I COSTS LESS GAS COMPARED TO I++ OR I += 1 IN FOR LOOPS (~5 GAS PER ITERATION)

Pre-increments are cheaper than post-increments.

For a uint256 i variable, pre-increment ++i costs 5 gas less than i++ with the optimizer enabled.

Note that post-increments (or post-decrements) return the old value before incrementing or decrementing, hence the name post-increment:
However, pre-increments (or pre-decrements) return the new value.

Instance:
https://github.com/code-423n4/2022-09-frax/blob/main/src/ERC20/ERC20PermitPermissionedMint.sol#L84

@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels Sep 25, 2022
code423n4 added a commit that referenced this issue Sep 25, 2022
code423n4 added a commit that referenced this issue Sep 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working G (Gas Optimization)
Projects
None yet
Development

No branches or pull requests

1 participant