Platform: Code4rena
Start Date: 24/03/2022
Pot Size: $75,000 USDC
Total HM: 15
Participants: 59
Period: 7 days
Judge: gzeon
Id: 103
League: ETH
Rank: 56/59
Findings: 1
Award: $67.06
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Dravee
Also found by: 0v3rf10w, 0xDjango, 0xNazgul, 0xkatana, ACai, CertoraInc, FSchmoede, Funen, Hawkeye, IllIllI, Jujic, Kenshin, PPrieditis, Picodes, SolidityScan, TerrierLover, Tomio, WatchPug, catchup, csanuragjain, defsec, dimitri, hake, hickuphh3, kenta, minhquanym, obront, peritoflores, rayn, rfa, robee, saian, samruna, tchkvsky, teryanarmen, ych18
67.0619 USDC - $67.06
function order will also have an impact on gas consumption. Because this contract, there is a difference in order of the function so this implementation below can be using for saving more gas (±12 gas)
##Tool Used Remix
#POC
IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1); bytes4[] memory functionSelectors = new bytes4[](1); functionSelectors[0] = IDiamondCut.diamondCut.selector; cut[0] = IDiamondCut.FacetCut({ facetAddress: _diamondCutFacet, action: IDiamondCut.FacetCutAction.Add, functionSelectors: functionSelectors }); LibDiamond.diamondCut(cut, address(0), ""); }
can be changed into :
bytes4[] memory functionSelectors = new bytes4[](1); IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1); functionSelectors[0] = IDiamondCut.diamondCut.selector; cut[0] = IDiamondCut.FacetCut({ facetAddress: _diamondCutFacet, action: IDiamondCut.FacetCutAction.Add, functionSelectors: functionSelectors }); LibDiamond.diamondCut(cut, address(0), ""); }
Using i++ instead ++i for all the loops, the variable i is incremented using i++. It is known that implementation by using ++i costs less gas per iteration than i++.
Remix
main/src/Facets/Swapper.sol#L14 main/src/Facets/HopFacet.sol#L48 main/src/Facets/DiamondLoupeFacet.sol#L24 main/src/Facets/DexManagerFacet.sol#L33 main/src/Facets/DexManagerFacet.sol#L52 main/src/Facets/DexManagerFacet.sol#L65
instead of using operator && on single require check. using additional require check can save more gas.
##Tool Used Remix
##POC
require( ls.dexWhitelist[_swapData[i].approveTo] == true && ls.dexWhitelist[_swapData[i].callTo] == true, "Contract call not allowed!" );
can be changed to :
require(ls.dexWhitelist[_swapData[i].approveTo] == true, "Contract call not allowed!"); require(ls.dexWhitelist[_swapData[i].callTo] == true, "Contract call not allowed!");
require
instead of Assert
for saving more gasAssert-style exceptions consume all gas available to the call. on other hand, using require-style exception will not consume any gas. it would be saving more gas by using require instead of assert.
##Tool Used Remix
##POC
https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/WithdrawFacet.sol#L30 https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/WithdrawFacet.sol#L34
assert(_amount <= self.balance); assert(_amount <= assetBalance);
change to
require(_amount <= self.balance); require(_amount <= assetBalance);
https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/AnyswapFacet.sol#L20 This implementation can be used for saving more gas (24 gas)
##Tool Used Remix
##POC
struct AnyswapData { address token; address router; uint256 amount; address recipient; uint256 toChainId; }
change to :
struct AnyswapData { address token; address router; address recipient; uint256 amount; uint256 toChainId; }
SafeERC20.function
to saving more gasthis implementation can be used for another gas opt
##Tool used Remix
##POC by not declare :
using SafeERC20 for IERC20;
and change at : https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/WithdrawFacet.sol#L35
SafeERC20.safeTransfer(IERC20(_assetAddress), sendTo, _amount);
its cheaper to using type(uint).max instead of using 2**256-1 calculation for unlimited approval
POC : LibAsset.sol #L15
https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Libraries/LibAsset.sol#L15
uint256 private constant MAX_INT = 2**256 - 1;
Every reason string takes at least 32 bytes. Use short reason strings that fits in 32 bytes or it will become more expensive.
Occurance :
LibDiamond.sol #L102 LibDiamond.sol #L187 LibDiamond.sol #L189
calldata
can be using memory
for saving more gashttps://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/CBridgeFacet.sol#L57 This implementation can be using for saving more gas.
##Tool used Remix
##POC
function startBridgeTokensViaCBridge(LiFiData memory _lifiData, CBridgeData calldata _cBridgeData) public payable { // ---> 2166900 deploy
can be changed to
function startBridgeTokensViaCBridge(LiFiData memory _lifiData, CBridgeData memory _cBridgeData) public payable { // ---> 2133888 deploy
#0 - H3xept
2022-04-08T14:32:21Z
Duplicate of #197
#1 - H3xept
2022-04-11T10:30:01Z
Duplicate of #100
#2 - H3xept
2022-04-11T10:50:43Z
Duplicate of #178
#3 - H3xept
2022-04-11T11:21:12Z
Duplicate of #165
#4 - H3xept
2022-04-11T12:03:35Z
We internally decided to avoid previx increments for now.
#5 - H3xept
2022-04-11T12:41:33Z
Duplicate of #152
#6 - H3xept
2022-04-11T12:51:00Z
Duplicate of #183