LI.FI contest - 0v3rf10w's results

Bridge & DEX Aggregation.

General Information

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

LI.FI

Findings Distribution

Researcher Performance

Rank: 33/59

Findings: 2

Award: $314.96

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

132.5612 USDC - $132.56

Labels

bug
sponsor disputed
QA (Quality Assurance)

External Links

l-01:

require statement is used after action/needed, put require above action AnyswapFacet.sol L#45

LibAsset.transferFromERC20(underlyingToken, msg.sender, address(this), _anyswapData.amount); require( LibAsset.getOwnBalance(underlyingToken) - _fromTokenBalance == _anyswapData.amount, "ERR_INVALID_AMOUNT" );

require should be before transfer to check amount correctly Other places : CBridgeFacet.sol L#63

l-02:

removeDex() is using batchRemoveDex() logic which is irrelevant, either remove loop part of removeDex() or remove one of the functions

DexManagerFace.sol L#52-55, this loop is also used in batchRemoveDex() which is not logical

l-03:

require statement is missing in GenericSwapFacet.sol to check validity of postSwapBalance as used in other swapfacets

l-04:

!= is missing in if statement HopFacet.sol L#64 I think if (sendingAssetId == address(0)) should be if (sendingAssetId != address(0)) else it doesn't make sense

here too, NXTPFacet.sol L#52

#0 - H3xept

2022-03-30T09:07:22Z

l-01

If the require was to be executed before the action transferFromERC20 the condition would always result in an identity check. (Relevant code below)


            uint256 _fromTokenBalance = LibAsset.getOwnBalance(underlyingToken);
            LibAsset.transferFromERC20(underlyingToken, msg.sender, address(this), _anyswapData.amount);

            require(
                LibAsset.getOwnBalance(underlyingToken) - _fromTokenBalance == _anyswapData.amount,
                "ERR_INVALID_AMOUNT"
            );

#1 - H3xept

2022-03-30T09:17:19Z

l-02:

The loop in question (below) is just a way to find and remove a dex from the dexs array. To my knowledge, this is the standard way of doing an in-place element removal from an array in Solidity.

        for (uint256 i = 0; i < s.dexs.length; i++) {
            if (s.dexs[i] == _dex) {
                _removeDex(i);
                return;
            }
        }

#2 - H3xept

2022-03-30T09:39:20Z

I-03

I will add a GT0 check as:

#3 - H3xept

2022-03-30T09:46:53Z

I-04

Other Facets reuse the same logic. If tokenId == 0x0 the bridging is started with the value sent along with the transaction, hence there's no token to transfer, just native gas currency.

Awards

182.4023 USDC - $182.40

Labels

bug
G (Gas Optimization)
resolved
sponsor acknowledged

External Links

g01:

floating pragma should not be used, prefer to fix it to 0.8.10

g02:

break && into two require statements to save gas AnyswapFacet.sol L#37, 80 Swapper.sol L#15

g03:

declaring functions external instead of public can save gas

g04:

use custom errors error() or try to use error codes/ shorten strings in require statements for saving gas similar to LibAsset.sol L#50

g05:

use uint256 instead of uint64,32,etc.. CBridgeFacet.sol L#21,30,32 HopFacet.sol L#48 Swapper.sol L#14

g06:

use calldata instead of memory to save gas AnyswapFacet.sol L#77,131 CBridgeFacet.sol L#95,142

g07:

use prefix instead of suffix to save gas, {++i} instead of i++ As all these functions are used a lot, hence in long run, gas saving are enough to be worth it DexManagerFacet.sol L#33,52,65 DiamondLoupeFacet.sol L#24 HopFacet.sol L#48 Swapper.sol L#14 LibDiamond.sol L#67,97

g08:

try to use immutable to save gas for fixed constants to save gas e.g. LibAsset.sol L#15,21 LibSwap.sol L#8

g09:

use != instead of > to save gas for uint as they can't be negative LibDiamond.sol L#102,121

#0 - H3xept

2022-04-08T14:49:53Z

Re g04

Duplicate of #44

#1 - H3xept

2022-04-08T14:50:20Z

Re prefix increment

We internally decided to avoid prefix increments for now.

#2 - H3xept

2022-04-08T15:06:34Z

Re external functions

Duplicate of #197

#3 - H3xept

2022-04-11T11:09:26Z

Re g09

Duplicate of #100

#4 - H3xept

2022-04-11T11:54:08Z

Re uintx to uint256

Duplicate of #196

#5 - H3xept

2022-04-11T12:40:26Z

Re calldata instead of memory for read-only arguments

Duplicate of #152

#6 - H3xept

2022-04-11T12:53:26Z

Re constant pre-computation

Duplicate of #182

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter