contracts/farming/LPFarming.sol:281: for (uint256 pid = 0; pid < length; ++pid) {
contracts/farming/LPFarming.sol:348: for (uint256 i = 0; i < poolInfo.length; i++) {
contracts/test/CryptoPunks.sol:114: for (uint256 i = 0; i < n; i++) {
contracts/test/CryptoPunks.sol:17: uint256 public nextPunkIndexToAssign = 0;
contracts/test/CryptoPunks.sol:20: uint256 public punksRemainingToAssign = 0;
contracts/test/MockAggregator.sol:15: uint256 constant public version = 0;
contracts/test/MockCurve.sol:18: for (uint256 i = 0; i < amounts.length; i++) {
contracts/test/MockRewardPool.sol:40: for (uint256 i = 0; i < extraRewards.length; i++) {
contracts/vaults/NFTVault.sol:181: for (uint256 i = 0; i < _typeInitializers.length; i++) {
contracts/vaults/NFTVault.sol:184: for (uint256 j = 0; j < initializer.nfts.length; j++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:145: for (uint256 i = 0; i < _strategyConfig.rewardTokens.length; i++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:231: for (uint256 i = 0; i < length; i++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:319: for (uint256 i = 0; i < rewardTokens.length; i++) {
contracts/test/CryptoPunks.sol:19: bool public allPunksAssigned = false;
contracts/vaults/FungibleAssetVaultForDAO.sol:45: address internal constant ETH = address(0);
Unchecked increment can be used in for-loop
Newer versions of the Solidity compiler will check for integer overflows and underflows automatically. This provides safety but increases gas costs.
When an unsigned integer is guaranteed to never overflow, the unchecked feature of Solidity can be used to save gas costs.
A common case for this is for-loops using a strictly-less-than comparision in their conditional statement, e.g.:
uint256 length = someArray.length;
for (uint256 i; i < length; ++i) {
}
In cases like this, the maximum value for length is 2**256 - 1. Therefore, the maximum value of i is 2**256 - 2 as it will always be strictly less than length.
This example can be replaced with the following construction to reduce gas costs:
for (uint i = 0; i < length; i = unchecked_inc(i)) {
// do something that doesn't change the value of i
}
function unchecked_inc(uint i) returns (uint) {
unchecked {
return i + 1;
}
}
For more information, consult the following resources:
contracts/farming/LPFarming.sol:281: for (uint256 pid = 0; pid < length; ++pid) {
contracts/farming/LPFarming.sol:348: for (uint256 i = 0; i < poolInfo.length; i++) {
contracts/test/CryptoPunks.sol:114: for (uint256 i = 0; i < n; i++) {
contracts/test/MockCurve.sol:18: for (uint256 i = 0; i < amounts.length; i++) {
contracts/test/MockRewardPool.sol:40: for (uint256 i = 0; i < extraRewards.length; i++) {
contracts/vaults/NFTVault.sol:181: for (uint256 i = 0; i < _typeInitializers.length; i++) {
contracts/vaults/NFTVault.sol:184: for (uint256 j = 0; j < initializer.nfts.length; j++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:145: for (uint256 i = 0; i < _strategyConfig.rewardTokens.length; i++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:231: for (uint256 i = 0; i < length; i++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:319: for (uint256 i = 0; i < rewardTokens.length; i++) {
Replace postfix increment (var++) with prefix increment (++var)
Using ++i costs less gas than using i++. In the context of a for-loop, gas is saved on each iteration.
The following lines of code are affected:
contracts/farming/LPFarming.sol:348: for (uint256 i = 0; i < poolInfo.length; i++) {
contracts/test/CryptoPunks.sol:114: for (uint256 i = 0; i < n; i++) {
contracts/test/EtherRocks.sol:59: rocks[rockNumber].timesSold++;
contracts/test/EtherRocks.sol:67: latestNewRockForSale++;
contracts/test/MockAggregator.sol:39: latestRound++;
contracts/test/MockCurve.sol:18: for (uint256 i = 0; i < amounts.length; i++) {
contracts/test/MockRewardPool.sol:40: for (uint256 i = 0; i < extraRewards.length; i++) {
contracts/vaults/NFTVault.sol:181: for (uint256 i = 0; i < _typeInitializers.length; i++) {
contracts/vaults/NFTVault.sol:184: for (uint256 j = 0; j < initializer.nfts.length; j++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:145: for (uint256 i = 0; i < _strategyConfig.rewardTokens.length; i++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:319: for (uint256 i = 0; i < rewardTokens.length; i++) {
When checking whether a value is equal to zero, using the construction var != 0 is costs less gas than using var > 0. Note that this is true only when the comparison occurs in a conditional context and the Solidity compiler is using the Optimizer.
For more information, please consult the following resources:
In the context of a for-loop that iterates over an array, it costs less gas to cache the array's length in a variable and read from this variable rather than use the arrays .length property. Reading the .length property for on the array will cause a recalculation of the array's length on each iteration of the loop which is a more expensive operation than reading from a stack variable.
For example, the following code:
for (uint i; i < arr.length; ++i) {
// ...
}
should be changed to:
uint length = arr.length;
for (uint i; i < length; ++i) {
// ...
}
Note that in the second case, the length of the array must not change during the loop's execution.
contracts/farming/LPFarming.sol:348: for (uint256 i = 0; i < poolInfo.length; i++) {
contracts/test/MockCurve.sol:18: for (uint256 i = 0; i < amounts.length; i++) {
contracts/test/MockRewardPool.sol:40: for (uint256 i = 0; i < extraRewards.length; i++) {
contracts/vaults/NFTVault.sol:181: for (uint256 i = 0; i < _typeInitializers.length; i++) {
contracts/vaults/NFTVault.sol:184: for (uint256 j = 0; j < initializer.nfts.length; j++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:145: for (uint256 i = 0; i < _strategyConfig.rewardTokens.length; i++) {
contracts/vaults/yVault/strategies/StrategyPUSDConvex.sol:319: for (uint256 i = 0; i < rewardTokens.length; i++) {
Gas Report
Variables do not need to be initialized with 'empty' values such as 0, false, or address(0)
Uninitialized variables by default contain a value equivalent to 0:
uint
s are initialized to 0;bool
s to false;address
es toaddress(0)
.Explicitly assigning these values to variables when they are declared increases gas costs while providing no funciton.
e.g. change this code:
uint256 var = 0;
to
uint256 var;
For more information, please consult the following resources:
Tips and Tricks to Save Gas and Reduce Bytecode Size
The following lines of code are affected:
Unchecked increment can be used in for-loop
Newer versions of the Solidity compiler will check for integer overflows and underflows automatically. This provides safety but increases gas costs.
When an unsigned integer is guaranteed to never overflow, the
unchecked
feature of Solidity can be used to save gas costs.A common case for this is for-loops using a strictly-less-than comparision in their conditional statement, e.g.:
In cases like this, the maximum value for
length
is2**256 - 1
. Therefore, the maximum value ofi
is2**256 - 2
as it will always be strictly less thanlength
.This example can be replaced with the following construction to reduce gas costs:
For more information, consult the following resources:
Solidity gas optimizations
Solidity docs: underflows, overflows, and unchecked
The following lines of code are affected:
Replace postfix increment (var++) with prefix increment (++var)
Using
++i
costs less gas than usingi++
. In the context of a for-loop, gas is saved on each iteration.The following lines of code are affected:
Replace strict greater-than-zero operation (> 0) with does-not-equal-zero (!= 0) operation
When checking whether a value is equal to zero, using the construction
var != 0
is costs less gas than usingvar > 0
. Note that this is true only when the comparison occurs in a conditional context and the Solidity compiler is using the Optimizer.For more information, please consult the following resources:
Twitter discussion detailing the gas costs of != 0 vs > 0 in require() calls
Solidity Compiler: Optimizer options
The following lines of code are affected:
Array length can be cached
In the context of a for-loop that iterates over an array, it costs less gas to cache the array's length in a variable and read from this variable rather than use the arrays
.length
property. Reading the.length
property for on the array will cause a recalculation of the array's length on each iteration of the loop which is a more expensive operation than reading from a stack variable.For example, the following code:
should be changed to:
Note that in the second case, the length of the array must not change during the loop's execution.
For more information, see the following resource:
Solidity gas optimizations
The following lines of code are affected: