There is no risk of overflow caused by increments to the iteration index in for loops (the i++ in for (uint256 i = 0; i < numIterations; i++)). Increments perform overflow checks that are not necessary in this case.
Recommendation
Surround the increment expressions with an unchecked { ... } block to avoid the default overflow checks. For example, change the loop
for (uint256 i = 0; i < numIterations; i++) {
// ...
}
to
for (uint256 i = 0; i < numIterations;) {
// ...
unchecked { i++; }
}
It is a little less readable but it saves a significant amount of gas.
Unnecessary SLOADs and MLOADs in for-each loops
There are many for loops that follows this for-each pattern:
for (uint256 i = 0; i < array.length; i++) {
// do something with `array[i]`
}
In such for loops, the array.length is read on every iteration, instead of caching it once in a local variable and read it from there. Storage reads are much more expensive than reading local variables. Memory reads are a bit more expensive than reading local variables.
Recommendation
Read these values from storage / memory once, cache them in local variables and then read them again from the local variables. For example:
uint256 length = array.length;
for (uint256 i = 0; i < length; i++) {
// do something with `array[i]`
}
Prefix increments / decrements are cheaper than postfix increments / decrements
Use prefix increments / decrements (++x / --x) instead of postfix increments / decrements (x++ / x--).
Recommendation
Change all postfix increments / decrements to prefix increments / decrements.
Unnecessary checked arithmetic in for loops
There is no risk of overflow caused by increments to the iteration index in for loops (the
i++
infor (uint256 i = 0; i < numIterations; i++)
). Increments perform overflow checks that are not necessary in this case.Recommendation
Surround the increment expressions with an
unchecked { ... }
block to avoid the default overflow checks. For example, change the loopto
It is a little less readable but it saves a significant amount of gas.
Unnecessary SLOADs and MLOADs in for-each loops
There are many for loops that follows this for-each pattern:
In such for loops, the
array.length
is read on every iteration, instead of caching it once in a local variable and read it from there. Storage reads are much more expensive than reading local variables. Memory reads are a bit more expensive than reading local variables.Recommendation
Read these values from storage / memory once, cache them in local variables and then read them again from the local variables. For example:
Prefix increments / decrements are cheaper than postfix increments / decrements
Use prefix increments / decrements (++x / --x) instead of postfix increments / decrements (x++ / x--).
Recommendation
Change all postfix increments / decrements to prefix increments / decrements.