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 #166

Open
code423n4 opened this issue Mar 16, 2022 · 0 comments
Open

Gas Optimizations #166

code423n4 opened this issue Mar 16, 2022 · 0 comments
Labels
bug Something isn't working G (Gas Optimization)

Comments

@code423n4
Copy link
Contributor

Gas Optimizations

Unused state variable

Description

Unused state variable.

Findings

LPToken.NATIVE

Recommended mitigation steps

Remove unused state variables to safe gas.

Public functions that could be declared external to save gas

Description

Following functions should be declared external, as functions that are never called by the contract internally should be declared external to save gas.

Findings

ExecutorManager.getExecutorStatus()
ExecutorManager.getAllExecutors()
LiquidityFarming.setRewardPerSecond()
LiquidityFarming.getNftIdsStaked()
LiquidityFarming.getRewardRatePerSecond()
LiquidityPool.setTrustedForwarder()
LiquidityPool.setLiquidityProviders()
LiquidityPool.getExecutorManager()
LiquidityProviders.getTotalReserveByToken()
LiquidityProviders.getSuppliedLiquidityByToken()
LiquidityProviders.getTotalLPFeeByToken()
LiquidityProviders.getCurrentLiquidity()
LiquidityProviders.increaseCurrentLiquidity()
LiquidityProviders.decreaseCurrentLiquidity()
LiquidityProviders.getFeeAccumulatedOnNft()
LPToken.setSvgHelper()
LPToken.getAllNftIdsByUser()
LPToken.exists()
TokenManager.getEquilibriumFee()
TokenManager.getMaxFee()
TokenManager.getTokensInfo()
TokenManager.getDepositConfig()
TokenManager.getTransferConfig()

Recommended mitigation steps

Use the external attribute for functions never called from the contract.

> 0 is less efficient than != 0 for unsigned integers

Description

!= 0 is a cheaper (less gas) operation for unsigned integers within require statements compared to > 0.

Findings

LiquidityProviders.sol#L239
LiquidityProviders.sol#L283
LiquidityProviders.sol#L410

Recommended mitigation steps

Change > 0 to != 0.

Avoid long revert strings

Description

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.

Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc.

Findings

ExecutorManager.sol#L17
LiquidityPool.sol#L77

Use unchecked {} primitive within for loops

Given the use of Solidity compiler >= 0.8.0, there are default arithmetic checks for mathematical operations which consume additional gas for such checks internally. In expressions where we are absolutely sure of no overflows/underflows, one can use the unchecked primitive to wrap such expressions to avoid checks and save gas.

Findings

ExecutorManager.sol#L31

Change to

for (uint256 i = 0; i < executorArray.length;) {
  addExecutor(executorArray[i]);

  unchecked { ++i; }
}

Also here:

ExecutorManager.sol#L47
LiquidityFarming.sol#L233
WhitelistPeriodManager.sol#L180
WhitelistPeriodManager.sol#L228
WhitelistPeriodManager.sol#L248
LPToken.sol#L77
TokenManager.sol#L78

An array's length should be cached to save gas in for-loops

Reading array length at each iteration of the loop takes 6 gas (3 for mload and 3 to place memory_offset) in the stack.

Caching the array length in the stack saves around 3 gas per iteration.

Recommended implementation

uint length = arr.length;

for (uint i; i < length; ++i) {
  // Operations not effecting the length of the array.
}

Findings

ExecutorManager.sol#L31
ExecutorManager.sol#L47
LiquidityFarming.sol#L233
WhitelistPeriodManager.sol#L180
WhitelistPeriodManager.sol#L228
WhitelistPeriodManager.sol#L248
LPToken.sol#L77
TokenManager.sol#78

Reorder require statements in LiquidityPool.sol:sendFundsToUser() to save gas on revert

Description

Require statements can be placed earlier to reduce gas usage on revert.

Findings

LiquidityPool.sol#L271

Recommended implementation

function sendFundsToUser(
    address tokenAddress,
    uint256 amount,
    address payable receiver,
    bytes memory depositHash,
    uint256 tokenGasPrice,
    uint256 fromChainId
) external nonReentrant onlyExecutor tokenChecks(tokenAddress) whenNotPaused {
    require(
        tokenManager.getTransferConfig(tokenAddress).min <= amount &&
            tokenManager.getTransferConfig(tokenAddress).max >= amount,
        "Withdraw amnt not in Cap limits"
    );
    require(receiver != address(0), "Bad receiver address");

    uint256 initialGas = gasleft();

    (bytes32 hashSendTransaction, bool status) = checkHashStatus(tokenAddress, amount, receiver, depositHash);

    ...
}

Reorder require statements in LiquidityProviders.sol:_increaseLiquidity() to save gas on revert

Description

Require statements can be placed earlier to reduce gas usage on revert.

Findings

LiquidityProviders.sol#L283

Recommended implementation

function _increaseLiquidity(uint256 _nftId, uint256 _amount) internal onlyValidLpToken(_nftId, _msgSender()) {
  require(_amount > 0, "ERR__AMOUNT_IS_0"); // @audit-info reorder require to top of function

  (address token, uint256 totalSuppliedLiquidity, uint256 totalShares) = lpToken.tokenMetadata(_nftId);

  whiteListPeriodManager.beforeLiquidityAddition(_msgSender(), token, _amount);

  ...
}

Reorder require statements in LiquidityProviders.sol:increaseNativeLiquidity() to save gas on revert

Description

Require statements can be placed earlier to reduce gas usage on revert.

Findings

LiquidityProviders.sol#L334

Recommended implementation

function increaseNativeLiquidity(uint256 _nftId) external payable nonReentrant whenNotPaused {
  require(_isSupportedToken(NATIVE), "ERR__TOKEN_NOT_SUPPORTED"); // @audit-info reorder require to top of function
  (address token, , ) = lpToken.tokenMetadata(_nftId);
  require(token == NATIVE, "ERR__WRONG_FUNCTION");
  (bool success, ) = address(liquidityPool).call{value: msg.value}("");

  ...
}

Remove unused variable access in modifier onlyValidLpToken()

Description

See @audit-info in following code snippet:

modifier onlyValidLpToken(uint256 _tokenId, address _transactor) {
    (address token, , ) = lpToken.tokenMetadata(_tokenId); // @audit-info not needed
    require(lpToken.exists(_tokenId), "ERR__TOKEN_DOES_NOT_EXIST");
    require(lpToken.ownerOf(_tokenId) == _transactor, "ERR__TRANSACTOR_DOES_NOT_OWN_NFT");
    _;
}

Findings

LiquidityProviders.sol#L54

Unused named returns can be removed

Description

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

Recommended mitigation steps

Remove the unused named return variables or use them instead of creating additional variables.

Findings

hyphen/token/TokenManager.sol

L139 unnecessary named return sender

hyphen/LiquidityProviders.sol

L457 unnecessary named return sender

hyphen/LiquidityFarming.sol

L351 unnecessary named return sender

hyphen/LiquidityPool.sol

L416 unnecessary named return sender

@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels Mar 16, 2022
code423n4 added a commit that referenced this issue Mar 16, 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 G (Gas Optimization)
Projects
None yet
Development

No branches or pull requests

1 participant