code-423n4 / 2022-06-infinity-findings

4 stars 0 forks source link

Gas Optimizations #309

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

[Gas-1] Use != 0 instead of > 0 on uint variables

uint variables will never be lower than 0. Therefore, > 0 and != 0 have same meanings. Using != 0 can reduce the gas deployment cost, so it is worth using != 0 wherever possible.

This part can be written as follows:

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L392

require(numNonces != 0, 'cannot be empty');

[Gas-2] No need to set 0 on uint variables

The default value of uint varibles are 0. Therefore, there is no need to set 0 on uint variables. Not setting 0 on uint variables can reduce the deployment gas cost.

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L148

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L200

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L219

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L272

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L308

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L349

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L393

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L1048

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L1086

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L1109

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L1190

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L1206

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L76

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L82

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L197

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L199

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L214

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L216

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L244

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L246

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L247

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L289

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L290

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L291

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L318

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L320


[Gas-3] Use custom errors

Using custom errors can reduce the gas cost.

There are more than 50 callsites of require check with inline error message. Using the custom errors instead of the inline error messages can reduce the gas cost.


[Gas-4] Potential usage of unchecked

Following variables or operations can be wrapped by unchecked to reduce the gas cost.

[1] The condition startPrice > endPrice assures that priceDiff will not underflow.

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L1156

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityOrderBookComplication.sol#L333

uint256 priceDiff;
unchecked {
    priceDiff = startPrice > endPrice ? startPrice - endPrice : endPrice - startPrice;
}

[2] The condition require(userstakedAmounts[msg.sender][oldDuration].amount >= amount, ...) assures that userstakedAmounts[msg.sender][oldDuration].amount -= amount will not underflow

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/staking/InfinityStaker.sol#L99

unchecked { userstakedAmounts[msg.sender][oldDuration].amount -= amount; }

[3] The conditions require(block.timestamp >= previousEpochTimestamp + getEpochDuration(), ...) and require(currentEpoch < getMaxEpochs(), ...) assure that block.timestamp - previousEpochTimestamp and getMaxEpochs() - currentEpoch will not underflow

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/token/InfinityToken.sol#L65-L66

uint256 epochsPassedSinceLastAdvance;
uint256 epochsLeft;
unchecked {
    epochsPassedSinceLastAdvance = (block.timestamp - previousEpochTimestamp) / getEpochDuration();
    epochsLeft = getMaxEpochs() - currentEpoch;
}

[4] The conditions if (amount > noVesting), if (amount > vestedThreeMonths) and if (amount > vestedSixMonths) assure that amount = amount - noVesting, amount = amount - vestedThreeMonths and amount = amount - vestedSixMonths will not underflow respectively

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/staking/InfinityStaker.sol#L301

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/staking/InfinityStaker.sol#L305

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/staking/InfinityStaker.sol#L309

    if (amount > noVesting) {
      userstakedAmounts[user][Duration.NONE].amount = 0;
      userstakedAmounts[user][Duration.NONE].timestamp = 0;
      unchecked {
        amount = amount - noVesting;
      }
      if (amount > vestedThreeMonths) {
        userstakedAmounts[user][Duration.THREE_MONTHS].amount = 0;
        userstakedAmounts[user][Duration.THREE_MONTHS].timestamp = 0;
        unchecked {
            amount = amount - vestedThreeMonths;
        }
        if (amount > vestedSixMonths) {
          userstakedAmounts[user][Duration.SIX_MONTHS].amount = 0;
          userstakedAmounts[user][Duration.SIX_MONTHS].timestamp = 0;
          unchecked {
            amount = amount - vestedSixMonths;
          }
          if (amount > vestedTwelveMonths) {

[5] Using constant PROTOCOL_FEE_BPS will not underflow amount - protocolFee

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/core/InfinityExchange.sol#L1135-L1136

uint256 remainingAmount
uint256 protocolFee = (PROTOCOL_FEE_BPS * amount) / 10000;
unchecked {
    remainingAmount = amount - protocolFee;
}

[Gas-5] Usage of delete can reduce both deployments and methods gas cost

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/staking/InfinityStaker.sol#L328-L340

  function _clearUserStakedAmounts(address user) internal {
    // clear amounts
    delete userstakedAmounts[user][Duration.NONE];
    delete userstakedAmounts[user][Duration.THREE_MONTHS];
    delete userstakedAmounts[user][Duration.SIX_MONTHS];
    delete userstakedAmounts[user][Duration.TWELVE_MONTHS];
  }

https://github.com/code-423n4/2022-06-infinity/blob/main/contracts/staking/InfinityStaker.sol#L290-L325

  function _updateUserStakedAmounts(
    address user,
    uint256 amount,
    uint256 noVesting,
    uint256 vestedThreeMonths,
    uint256 vestedSixMonths,
    uint256 vestedTwelveMonths
  ) internal {
    if (amount > noVesting) {
      delete userstakedAmounts[user][Duration.NONE];
      amount = amount - noVesting;
      if (amount > vestedThreeMonths) {
        delete userstakedAmounts[user][Duration.THREE_MONTHS];
        amount = amount - vestedThreeMonths;
        if (amount > vestedSixMonths) {
          delete userstakedAmounts[user][Duration.SIX_MONTHS];
          amount = amount - vestedSixMonths;
          if (amount > vestedTwelveMonths) {
            delete userstakedAmounts[user][Duration.TWELVE_MONTHS];
          } else {
            userstakedAmounts[user][Duration.TWELVE_MONTHS].amount -= amount;
          }
        } else {
          userstakedAmounts[user][Duration.SIX_MONTHS].amount -= amount;
        }
      } else {
        userstakedAmounts[user][Duration.THREE_MONTHS].amount -= amount;
      }
    } else {
      userstakedAmounts[user][Duration.NONE].amount -= amount;
    }
  }