Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gas Optimizations #327

Open
code423n4 opened this issue May 25, 2022 · 0 comments
Open

Gas Optimizations #327

code423n4 opened this issue May 25, 2022 · 0 comments
Labels
bug Something isn't working duplicate This issue or pull request already exists G (Gas Optimization)

Comments

@code423n4
Copy link
Contributor

G01 - Comparison > 0 is less gas efficient than != 0 with uint256 in require statement

contracts/Aura.sol:68   require(_amount > 0, "Must mint something");
contracts/AuraBalRewardPool.sol:121    require(_amount > 0, "RewardPool : Cannot stake 0");
contracts/AuraBalRewardPool.sol:139    require(_amount > 0, "RewardPool : Cannot stake 0");
contracts/AuraBalRewardPool.sol:157    require(amount > 0, "RewardPool : Cannot withdraw 0");
contracts/AuraBalRewardPool.sol:210    require(rewardsAvailable > 0, "!balance");
contracts/AuraLocker.sol:210    require(rewardData[_rewardsToken].lastUpdateTime > 0, "Reward does not exist");
contracts/AuraLocker.sol:259    require(_amount > 0, "Cannot stake 0");
contracts/AuraLocker.sol:359    require(amt > 0, "Nothing locked");
contracts/AuraLocker.sol:385    require(length > 0, "no locks");
contracts/AuraLocker.sol:431    require(locked > 0, "no exp locks");
contracts/AuraLocker.sol:471    require(len > 0, "Nothing to delegate");
contracts/AuraLocker.sol:822    require(_rewards > 0, "No reward");
contracts/AuraLocker.sol:851    require(_reward > 0, "No reward");
contracts/AuraMerkleDrop.sol:122    require(_amount > 0, "!amount");
contracts/AuraPenaltyForwarder.sol:52   require(bal > 0, "!empty");
contracts/AuraVestedEscrow.sol:118  require(totalLocked[_recipient] > 0, "!funding");
contracts/BalLiquidityProvider.sol:57   require(bal > 0 && bal == _request.maxAmountsIn[i], "!bal");
contracts/BalLiquidityProvider.sol:70   require(balAfter > 0, "!mint");
contracts/ExtraRewardsDistributor.sol:171   require(_index > 0 && _index < rewardEpochs[_token].length - 1, "!past");
convex-platform/contracts/contracts/BaseRewardPool.sol:211  require(_amount > 0, 'RewardPool : Cannot stake 0');
convex-platform/contracts/contracts/BaseRewardPool.sol:227  require(amount > 0, 'RewardPool : Cannot withdraw 0');
convex-platform/contracts/contracts/CrvDepositor.sol:169    require(_amount > 0,"!>0");  
convex-platform/contracts/contracts/PoolManagerSecondaryProxy.sol:104   require(weight > 0, "must have weight");

G02 - No need to initialize variables with default values

If a variable is not set, it is assumed to have the default value (0, false etc).

contracts/AuraBalRewardPool.sol:35  uint256 public pendingPenalty = 0;
contracts/AuraBalRewardPool.sol:38  uint256 public periodFinish = 0;
contracts/AuraBalRewardPool.sol:39  uint256 public rewardRate = 0;
contracts/AuraLocker.sol:72    uint256 public queuedCvxCrvRewards = 0;
contracts/AuraLocker.sol:114    bool public isShutdown = false;
contracts/AuraMerkleDrop.sol:29   uint256 public pendingPenalty = 0;
contracts/AuraVestedEscrow.sol:33   bool public initialised = false;
convex-platform/contracts/contracts/BaseRewardPool.sol:71   uint256 public periodFinish = 0;
convex-platform/contracts/contracts/BaseRewardPool.sol:72   uint256 public rewardRate = 0;
convex-platform/contracts/contracts/BaseRewardPool.sol:75   uint256 public queuedRewards = 0;
convex-platform/contracts/contracts/BaseRewardPool.sol:76   uint256 public currentRewards = 0;
convex-platform/contracts/contracts/BaseRewardPool.sol:77   uint256 public historicalRewards = 0;
convex-platform/contracts/contracts/Booster.sol:29  uint256 public platformFee = 0; //possible fee to build treasury
convex-platform/contracts/contracts/CrvDepositor.sol:36 uint256 public incentiveCrv = 0;  
convex-platform/contracts/contracts/VirtualBalanceRewardPool.sol:89    uint256 public periodFinish = 0;
convex-platform/contracts/contracts/VirtualBalanceRewardPool.sol:90    uint256 public rewardRate = 0;
convex-platform/contracts/contracts/VirtualBalanceRewardPool.sol:93    uint256 public queuedRewards = 0;
convex-platform/contracts/contracts/VirtualBalanceRewardPool.sol:94    uint256 public currentRewards = 0;
convex-platform/contracts/contracts/VirtualBalanceRewardPool.sol:95    uint256 public historicalRewards = 0;

G03 - Variables that can be changed to immutable

contracts/AuraLocker.sol:117    string private _name;
contracts/AuraLocker.sol:118    string private _symbol;
contracts/ClaimFeesHelper.sol:23    IFeeDistributor public feeDistro;
convex-platform/contracts/contracts/BaseRewardPool4626.sol:26   address public override asset;
convex-platform/contracts/contracts/DepositToken.sol:22   address public operator;  
convex-platform/contracts/contracts/TokenFactory.sol:21   string public namePostfix;  
convex-platform/contracts/contracts/TokenFactory.sol:22   string public symbolPrefix;

G04 - Cache array length before for loop

Optimizing for loops by caching memory array length before loop, instead of calling it every time.

contracts/AuraClaimZap.sol:143    for (uint256 i = 0; i < rewardContracts.length; i++) {
contracts/AuraClaimZap.sol:147    for (uint256 i = 0; i < extraRewardContracts.length; i++) {
contracts/AuraClaimZap.sol:151    for (uint256 i = 0; i < tokenRewardContracts.length; i++) {
contracts/AuraLocker.sol:696    for (uint256 i = nextUnlockIndex; i < locks.length; i++) {
contracts/AuraVestedEscrow.sol:100    for (uint256 i = 0; i < _recipient.length; i++) {
convex-platform/contracts/contracts/ArbitartorVault.sol:49   for(uint256 i = 0; i < _toPids.length; i++){
convex-platform/contracts/contracts/BaseRewardPool.sol:214  for(uint i=0; i < extraRewards.length; i++){  
convex-platform/contracts/contracts/BaseRewardPool.sol:230  for(uint i=0; i < extraRewards.length; i++){  
convex-platform/contracts/contracts/BaseRewardPool.sol:262  for(uint i=0; i < extraRewards.length; i++){
convex-platform/contracts/contracts/BaseRewardPool.sol:296  for(uint i=0; i < extraRewards.length; i++){  
convex-platform/contracts/contracts/Booster.sol:379    for(uint i=0; i < poolInfo.length; i++){
convex-platform/contracts/contracts/Booster.sol:538   for(uint256 i = 0; i < _gauge.length; i++){
convex-platform/contracts/contracts/PoolManagerSecondaryProxy.sol:69    for(uint i=0; i < usedList.length; i++){  

G05 - Using ++i consumes less gas than i++

contracts/AuraClaimZap.sol:143    for (uint256 i = 0; i < rewardContracts.length; i++) {
contracts/AuraClaimZap.sol:147    for (uint256 i = 0; i < extraRewardContracts.length; i++) {
contracts/AuraClaimZap.sol:151    for (uint256 i = 0; i < tokenRewardContracts.length; i++) {
contracts/AuraLocker.sol:696    for (uint256 i = nextUnlockIndex; i < locks.length; i++) {
contracts/AuraVestedEscrow.sol:100    for (uint256 i = 0; i < _recipient.length; i++) {
contracts/AuraLocker.sol:174    for (uint256 i = 0; i < rewardTokensLength; i++) {
contracts/AuraLocker.sol:306    for (uint256 i; i < rewardTokensLength; i++) {
contracts/AuraLocker.sol:410    for (uint256 i = nextUnlockIndex; i < length; i++) {
contracts/AuraLocker.sol:664    for (uint256 i = locksLength; i > 0; i--) {
contracts/AuraLocker.sol:726    for (uint256 i = epochIndex + 1; i > 0; i--) {
contracts/AuraLocker.sol:773    for (uint256 i = 0; i < userRewardsLength; i++) {
contracts/ExtraRewardsDistributor.sol:233   for (uint256 i = epochIndex; i < tokenEpochs; i++) {

G06 - unchecked block can be used for gas efficiency of the expression that can't overflow/underflow

Check comments

contracts/AuraBalRewardPool.sol:185    rewardToken.safeTransfer(msg.sender, reward - penalty); // penalty <= reward due to L183
contracts/AuraLocker.sol:278    if (idx == 0 || userLocks[_account][idx - 1].unlockTime < unlockTime) { // If idx == 0 then first part return true, so here and on L281 can't be underflow
contracts/AuraLocker.sol:334    while (epochs[epochs.length - 1].date != currentEpoch) {  //  If epochs.length == 0 then it will be checked on L332, so here and on L335 can't be underflow
contracts/AuraLocker.sol:402    uint256 epochsover = currentEpoch.sub(uint256(locks[length - 1].unlockTime)).div(rewardsDuration); // length > 0, checked on L385, so here and on L404 can't be underflow
contracts/AuraLocker.sol:484    uint256 i = len - 1; // len > 0, checked on L471
contracts/AuraLocker.sol:497    i--; // i > 0, checked on L496
contracts/AuraLocker.sol:521    DelegateeCheckpoint memory prevCkpt = ckpts[ckpts.length - 1]; // ckpts.length > 0, checked on L520, so here and on L524 can't be underflow
contracts/AuraLocker.sol:640    return high == 0 ? DelegateeCheckpoint(0, 0) : ckpts[high - 1]; // can't be underflow due to statement logic
contracts/AuraLocker.sol:665    uint256 lockEpoch = uint256(locks[i - 1].unlockTime).sub(lockDuration); // i > 0, checked on L664, so here and on 670 can't be underflow
contracts/AuraLocker.sol:699    lockData = new LockedBalance[](locks.length - i); // i < locks.length due to L696
contracts/AuraLocker.sol:722    uint256 lastIndex = epochs.length - 1; // epochs.length > 0 due to L718
contracts/AuraLocker.sol:727    Epoch memory e = epochs[i - 1]; // i > 0 due to L726
contracts/AuraMerkleDrop.sol:138    aura.safeTransfer(msg.sender, _amount - penalty); // penalty < _amount due to L136
contracts/AuraVestedEscrow.sol:162  uint256 elapsed = _time - startTime;  // startTime < _time due to L158
contracts/ExtraRewardsDistributor.sol:74    require(len == 0 || rewardEpochs[_token][len - 1] < _epoch, "Cannot backdate to this epoch"); // if len == 0 then first part return true
contracts/ExtraRewardsDistributor.sol:102   if (len == 0 || rewardEpochs[_token][len - 1] < _epoch) { if len == 0 then first part return true

G07 - Too long revert strings

Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition has been met.

contracts/AuraLocker.sol:197    require(_rewardsToken != address(stakingToken), "Cannot add StakingToken as reward");

G08 - Named return vatiable

Removing unused named return variables can reduce gas usage and improve code clarity.

contracts/AuraLocker.sol:712    function totalSupply() external view returns (uint256 supply) {
contracts/AuraLocker.sol:739    function findEpochId(uint256 _time) public view returns (uint256 epoch) {
convex-platform/contracts/contracts/BaseRewardPool4626.sol:179  function previewWithdraw(uint256 assets) public view virtual override returns(uint256 shares){  

G09 - No needed +=

No need to use += instead of =, since totalLocked[_recipient[i]] always be 0 here:

contracts/AuraVestedEscrow.sol:103  totalLocked[_recipient[i]] += amount;

G10 - Caching storage values in memory

Variables that are read multiple times in a code block can be cached and re-used instead of reading from storage to save gas.

contracts/AuraLocker.sol:812    .div(lockedSupply) // lockedSupply 2 SLOAD
contracts/AuraMerkleDrop.sol:126    require(MerkleProof.verify(_proof, merkleRoot, leaf), "invalid proof"); // merkleRoot 2 SLOAD
contracts/AuraMerkleDrop.sol:132    aura.safeApprove(address(auraLocker), _amount); // auraLocker 2 SLOAD
contracts/AuraStakingProxy.sol:119  owner = pendingOwner; // pendingOwner 2 SLOAD
contracts/AuraStakingProxy.sol:148  IERC20(crv).safeApprove(crvDepositorWrapper, type(uint256).max); // crvDepositorWrapper 2 SLOAD
contracts/AuraStakingProxy.sol:151  IERC20(cvxCrv).safeApprove(rewards, type(uint256).max); // rewards 2 SLOAD
contracts/AuraStakingProxy.sol:172  require(msg.sender == keeper, "!auth"); // keeper 2 SLOAD
contracts/AuraStakingProxy.sol:179  ICrvDepositor(crvDepositorWrapper).deposit(crvBal, minOut, true, address(0)); // crvDepositorWrapper 2 SLOAD
contracts/AuraStakingProxy.sol:219  IAuraLocker(rewards).notifyRewardAmount(address(_token), bal); // rewards 3 SLOAD
contracts/AuraVestedEscrow.sol:186  rewardToken.safeApprove(address(auraLocker), claimable); // auraLocker 2 SLOAD
convex-platform/contracts/contracts/Booster.sol:235    emit FeeInfoUpdated(_feeDistro, lockRewards, crv); // lockRewards 3 SLOAD
convex-platform/contracts/contracts/Booster.sol:606   IERC20(crv).safeTransfer(treasury, _platform); // treasury 3 SLOAD
@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels May 25, 2022
code423n4 added a commit that referenced this issue May 25, 2022
@0xMaharishi 0xMaharishi added the duplicate This issue or pull request already exists label May 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working duplicate This issue or pull request already exists G (Gas Optimization)
Projects
None yet
Development

No branches or pull requests

2 participants