Open code423n4 opened 2 years ago
We could also use 1 and 2, agree
We could also just call sweeprewards separately for what it's worth
I fail to see how we would action this
These are memory values, I don't believe this to be valid
Agree
Agree
Valid but we're fine
Not particularly useful for Governance Variables
Nope
MSTORE is 3 gas ser
++i saves 5 gas compared to i++
Acknowledged
That changes the functionality of the contract
We're on 6.12 ser
Summary
Gas Optimizations
isClaimingBribes
back tofalse
wastes gassweepRewards()
internal
functions only called once can be inlined to save gas<array>.length
should not be looked up in every loop of afor
-looprequire()
/revert()
strings longer than 32 bytes cost extra gasbool
s for storage incurs overheadconstant
/non-immutable
variables to zero than to let the default of zero be applied++i
costs less gas thani++
, especially when it's used infor
-loops (--i
/i--
too)require()
statements that use&&
saves gasprivate
rather thanpublic
for constants, saves gasrevert()
/require()
strings to save gasTotal: 42 instances over 14 issues
Gas Optimizations
1. Repeatedly changing
isClaimingBribes
back tofalse
wastes gasChanging the value from
false
totrue
incurs a Gsset (20000 gas), checking it in thereceive()
incurs a Gwarmaccess (100 gas), and changing it back incurs a Gsreset (2900 gas). Instead you can store the last value ofhiddenHandDistributor
and change therequire()
in thereceive()
to only allow funds whenhiddenHandDistributor
ismsg.sender
, which after the first set, would change the Gsset to a Gsreset, and avoid the later GsresetThere is 1 instance of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L310-L312
2. Modifier should be skipped for
sweepRewards()
sweepRewards()
callssweepRewardToken()
for each token in the array, and each call ends up checking for governance, which incurs the cost of external calls to look up the governance and or strategist addresses, each of which incur the cost of at the minimum anEXTCODESIZE
(700 gas) plus the cost of an external callThere is 1 instance of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L108
3. Avoid contract existence checks by using solidity version 0.8.10 or later
Prior to 0.8.10 the compiler inserted extra code, including
EXTCODESIZE
(700 gas), to check for contract existence for external calls. In more recent solidity versions, the compiler will not insert these checks if the external call has a return valueThere are 9 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L57
4. Multiple accesses of a mapping/array should use a local variable cache
The instances below point to the second+ access of a value inside a mapping/array, within a function. Caching a mapping's value in a local
storage
variable when the value is accessed multiple times, saves ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations. Caching an array's struct avoids recalculating the array offsets into memoryThere are 5 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L154
5.
internal
functions only called once can be inlined to save gasNot inlining costs 20 to 40 gas because of two extra
JUMP
instructions and additional stack operations needed for function calls.There are 3 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L416-L417
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L421
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L428
6.
<array>.length
should not be looked up in every loop of afor
-loopThe overheads outlined below are PER LOOP, excluding the first loop
MLOAD
(3 gas)CALLDATALOAD
(3 gas)Caching the length changes each of these to a
DUP<N>
(3 gas), and gets rid of the extraDUP<N>
needed to store the stack offsetThere are 2 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L300
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L317
7.
require()
/revert()
strings longer than 32 bytes cost extra gasEach extra memory word of bytes past the original 32 incurs an MSTORE which costs 3 gas
There is 1 instance of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L184-L187
8. Using
bool
s for storage incurs overheadhttps://github.com/OpenZeppelin/openzeppelin-contracts/blob/58f635312aa21f947cae5f8578638a85aa2519f5/contracts/security/ReentrancyGuard.sol#L23-L27 Use
uint256(1)
anduint256(2)
for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD, and to avoid Gsset (20000 gas) when changing from 'false' to 'true', after having been 'true' in the pastThere are 3 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L24
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L26
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L28
9. Use a more recent version of solidity
Use a solidity version of at least 0.8.0 to get overflow protection without
SafeMath
Use a solidity version of at least 0.8.2 to get simple compiler automatic inlining Use a solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads Use a solidity version of at least 0.8.4 to get custom errors, which are cheaper at deployment thanrevert()/require()
strings Use a solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return valueThere is 1 instance of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L3
10. It costs more gas to initialize non-
constant
/non-immutable
variables to zero than to let the default of zero be appliedNot overwriting the default for stack variables saves 8 gas. Storage and memory variables have larger savings
There are 3 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L118
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L300
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L317
11.
++i
costs less gas thani++
, especially when it's used infor
-loops (--i
/i--
too)Saves 6 gas per loop
There are 3 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L118
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L300
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L317
12. Splitting
require()
statements that use&&
saves gasSee this issue which describes the fact that there is a larger deployment gas cost, but with enough runtime calls, the change ends up being cheaper
There is 1 instance of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L184-L187
13. Using
private
rather thanpublic
for constants, saves gasIf needed, the value can be read from the verified contract source code. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table
There are 3 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L45
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L46
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L47
14. Use custom errors rather than
revert()
/require()
strings to save gasCustom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they're hitby avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas
There are 6 instances of this issue:
https://github.com/Badger-Finance/vested-aura/blob/d504684e4f9b56660a9e6c6dfb839dcebac3c174/contracts/MyStrategy.sol#L184-L187