When incrementing i in for loops there is no chance of overflow so unchecked can be used to save gas. I ran a simple test in remix and found deployment savings of 31,653 gas and on each function call saved ~141 gas per iteration.
contract Test {
function loopTest() external {
for (uint256 i; i < 1; ++i) {
Deployment Cost: 125,637, Cost on function call: 24,601
vs
for (uint256 i; i < 1; ) {
// for loop body
unchecked { ++i }
Deployment Cost: 93,984, Cost on function call: 24,460
}
}
}
In for loops pre increments can also be used to save a small amount of gas per iteraition.
I ran a test in remix using a for loop and found the deployment savings of 497 gas and ~5 gas per iteration.
contract Test {
function loopTest() external {
for (uint256 i; i < 1; i++) {
(Deployment cost: 118,408, Cost on function call: 24,532)
vs
for (uint256 i; i < 1; ++i) {
(Deployment cost: 117,911, Cost on function call: 24,527)
}
}
}
Keeping revert strings <= 32 bytes in length will save gas.
I ran a test in remix and found the savings for a single short revert string vs long string to be 9,377 gas in deployment cost and 18 gas on function call.
contract Test {
uint256 a;
function check() external {
require(a != 0, "short error message");
(Deployment cost: 114,799, Cost on function call: 23,392)
vs
require(a != 0, "A longer Error Message over 32 bytes in
length");
(Deployment cost: 124,176, Cost on function call: 23,410)
}
}
I recommend shortenning the following revert strings to <= 32 bytes in length:
MyStrategy.sol#L186
G03 && in Require Functions
If optimising for running costs over deployment costs you can seperate && in require functions into 2 parts. I ran a basic test in remix and it cost an extra 234 gas to deploy but will save ~9 gas everytime the require function is called.
contract Test {
uint256 a = 0;
uint256 b = 1;
function test() external {
require(a == 0 && b > a)
(Deployment cost: 123,291, Cost on function call: 29,371)
vs
require(a == 0);
require(b > a);
(Deployment cost: 123,525, Cost on function call: 29,362)
}
}
G01 For Loop Optimisations
When incrementing i in for loops there is no chance of overflow so unchecked can be used to save gas. I ran a simple test in remix and found deployment savings of 31,653 gas and on each function call saved ~141 gas per iteration.
In for loops pre increments can also be used to save a small amount of gas per iteraition. I ran a test in remix using a for loop and found the deployment savings of 497 gas and ~5 gas per iteration.
Instances where unchecked and pre Increments can be implemented in for loops: MyStrategy.sol#L118 MyStrategy.sol#L153 - is already pre increment MyStrategy.sol#L300 MyStrategy.sol#L317
G02 Long Revert Strings
Keeping revert strings <= 32 bytes in length will save gas. I ran a test in remix and found the savings for a single short revert string vs long string to be 9,377 gas in deployment cost and 18 gas on function call.
I recommend shortenning the following revert strings to <= 32 bytes in length: MyStrategy.sol#L186
G03 && in Require Functions
If optimising for running costs over deployment costs you can seperate && in require functions into 2 parts. I ran a basic test in remix and it cost an extra 234 gas to deploy but will save ~9 gas everytime the require function is called.
MyStrategy.sol#L185