Gas Optimizations #299
Labels
bug
Something isn't working
duplicate
This issue or pull request already exists
G (Gas Optimization)
Gas Optimizations
Error messages length
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met. Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc.
An even better and gas efficient approach will be to use Solidity Custom Errors instead of revert strings.
Aura.sol
Pre-deploy calculation in
Aura
's constructorCalculate this calculation before the deployment to save gas:
reductionPerCliff = EMISSIONS_MAX_SUPPLY.div(totalCliffs);
AuraBalRewardPool.sol
Save return value of
totalSupply
instead of calling it twice in therewardPerToken
functionSave SLOADs
save the return value of
rewardPerToken
instead of accessing therewardPerTokenStored
variable twice in theupdateReward
modifiercache
duration
in theinitialiseRewards
functionredundant initialization
Variables in solidity are already initialized to their default value, and initializing them to the same value actually costs more gas. So the initialization of storage variables to 0 is redundant.
Make the calculation simpler
Replace
(reward * 2) / 10;
withreward / 5;
in thegetReward
functionAuraLocker.sol
save SLOADs
rewardsDuration
in this calculation instead of accessing it twice:uint256 currentEpoch = block.timestamp.div(rewardsDuration).mul(rewardsDuration);
_checkpointEpoch
,constructor
and_lock
.2 optimizations for the
updateReward
functionuserBalance.locked
to a memory variable. This will save an SLOAD.rewardData[token]
Cache
rewardData[_rewardsToken]
in the_rewardPerToken
functionCache
rewardTokens
in thegetReward
functionCache
rdata
in the_notifyReward
functionLoop optimizations
Loops can be optimized in several ways. Let's take for example the loop in the
_processExpiredLocks
function.locks[i]
instead of accessing the array's element multiple times in every iteration++i
) instead of postfix increment (i++
)This is the old code:
And this is the code after the suggested changes:
Loop optimizations like this can be done to more loops in the code. For example, you can also optimize the loop in the
updateReward
modifier:uint i;
instead ofuint i = 0;
.rewardData[token]
++i
) instead of postfix increment (i++
)This is the old code:
And this is the code after applying the suggestions:
Optimize calculations by removing unnecessary overflow checks
Let's take a look at the
_lock
function. In there, both the user's balance and the locked supply is being incremented:But we know that
bal.locked <= lockedSupply
, so we can know that ifbal.locked
will overflow,lockedSupply
will overflow too, so we can use unchecked onbal.locked
to save some gas.Another example is in the
_processExpiredLocks
, where the locked supply and user's balance are being decremented. Because we know thatbal.locked <= lockedSupply
, we can use unchecked on the subtraction from the locked supply because if it will underflow the subtraction will underflow too.redundant initialization on line 540
Initializing this variable to zero will cost more gas than just declaring the variable (the variable's value will be set to zero by default)
uint256 unlocksSinceLatestCkpt = 0;
AuraVestingEscrow.sol
Use unchecked in the
constructor
and in_totalVestedOf
In the constructor, we know that
endTime > startTime
, sototalTime = endTime - startTime;
won't underflow.In the
_totalVestedOf
we know that_time >= startTime
, souint256 elapsed = _time - startTime;
won't underflow.save an SLOAD
Cache
startTime
in the_totalVestedOf
functionThe text was updated successfully, but these errors were encountered: