code-423n4 / 2022-03-lifinance-findings

6 stars 4 forks source link

Gas Optimizations #178

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Summary for gas optimization

The contract was found to be using struct variables in random order. Since structs use packing and assign storage slots accordingly, lower to higher-order will save gas as lower variables get packed. We found many functions were declared as public but were never internally used. Such functions can always be marked as external instead of public as external functions consume less gas than public functions. We also noticed the contract uses power operations at a few places instead of using the exponential form directly, which would save gas.

Gas-1

Title:

Structs can be rearranged from lower to higher to save gas.

Description:

If the variable types in the struct are arranged in a lower to a higher order, the gas used is lesser than when they are arranged in any other order. The main goal here is the reduction of gas requirements when deploying these smart contracts, and saving costs in each place will eventually add up. The consequences of the use of the Tight Variable Packing pattern have to be evaluated before implementing it blindly. The big benefit comes from the substantial amount of gas that can potentially be saved over the lifetime of a contract.

PoC:

At line (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/CBridgeFacet.sol#L26-L33) We will notice that the structs are ordered as below

address receiver;
address token;
uint256 amount;
uint64 dstChainId;
uint64 nonce;
uint32 maxSlippage;

This will consume 370235 gas

However the struct is arranged in lower to higher order. The lower ones will get packed in a single slot and hence it will save gas.

uint32 maxSlippage;
uint64 dstChainId;
uint64 nonce;
uint256 amount;
address receiver;
address token; 

The above arrangement will consume 370199 gas

image.png

Suggested Fix:

Arrange the struct variable from lower to higher order.

Gas-2

Title:

Functions that can be external instead of public

Description:

Public functions that are never called by a contract should be declared external in order to conserve gas.

Impact

Smart Contracts are required to have effective Gas usage as they cost real money, and each function should be monitored for the amount of gas it costs to make it gas efficient.

Public functions cost more Gas than external functions.

PoC:

The following functions can be declared external: 1) Function setRewardForwarding (https://github.com/code-423n4/2022-02-redacted-cartel/blob/main/contracts/TokemakBribe.sol#L298-L302) 2) Function swapAndStartBridgeTokensViaAnyswap (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/AnyswapFacet.sol#L74-L123)

  1. Function startBridgeTokensViaCBridge (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/CBridgeFacet.sol#L57-L84)
  2. Function swapAndStartBridgeTokensViaCBridge (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/CBridgeFacet.sol#L92-L134)
  3. Function swapTokensGeneric (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/GenericSwapFacet.sol#L22-L44)
  4. Function startBridgeTokensViaHop (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/HopFacet.sol#L61-L87)
  5. Function swapAndStartBridgeTokensViaHop (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/HopFacet.sol#L95-L126)
  6. Function startBridgeTokensViaNXTP (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/NXTPFacet.sol#L46-L76)
  7. Function swapAndStartBridgeTokensViaNXTP (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/NXTPFacet.sol#L85-L115)
  8. Function completeBridgeTokensViaNXTP (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/NXTPFacet.sol#L124-L140)
  9. Function swapAndCompleteBridgeTokensViaNXTP (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/NXTPFacet.sol#L150-L171)
  10. Function withdraw (https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/WithdrawFacet.sol#L20-L38)

Suggested Fix:

Use the external state visibility for functions that are never called from the contract.

Gas-3

Title:

Use of power operations instead of their exponential form

Description:

It is unnecessary to perform power operations when a number can be directly represented in an exponential form as it will save gas.

PoC:

  1. At https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Libraries/LibAsset.sol#L15 2e256 can be used instead of 2**256
  2. At https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Libraries/LibSwap.sol#L8 2e256 can be used instead of 2**256

Suggested Fix:

Use exponential form instead of power operations to save gas.

H3xept commented 2 years ago

Re: Gas-2

Fixed in lifinance/lifi-contracts@26443af0142afdb131b6b3ab278fac29670b7b0e

H3xept commented 2 years ago

Re Gas-3

This won't compile as the intermediate result 2e256 does not fin in uint256.

H3xept commented 2 years ago

Re external functions

Duplicate of #197