LI.FI contest - wuwe1'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: 15/59

Findings: 4

Award: $1,265.32

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Findings Information

🌟 Selected for report: hake

Also found by: Kenshin, Ruhum, VAD37, WatchPug, csanuragjain, hickuphh3, hyh, kirk-baird, obront, pmerkleplant, rayn, shw, tintin, wuwe1

Labels

bug
duplicate
2 (Med Risk)
disagree with severity
sponsor acknowledged

Awards

77.3842 USDC - $77.38

External Links

Lines of code

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Libraries/LibSwap.sol#L33

Vulnerability details

Proof of Concept

  1. LibSwap.swap only transfer msg.sender token when LibAsset.getOwnBalance(fromAssetId) < fromAmount

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Libraries/LibSwap.sol#L33-L35

if (!LibAsset.isNativeAsset(fromAssetId) && LibAsset.getOwnBalance(fromAssetId) < fromAmount) {
    LibAsset.transferFromERC20(fromAssetId, msg.sender, address(this), fromAmount);
}
  1. Anyone can set fromAmount equal to LibAsset.getOwnBalance(fromAssetId). By doing this all of the token in the contract will be swapped to specified token and transfer to msg.sender

Consider change to this. Always transfer the token.

if (!LibAsset.isNativeAsset(fromAssetId)) {
    LibAsset.transferFromERC20(fromAssetId, msg.sender, address(this), fromAmount);
}

#0 - H3xept

2022-04-12T08:39:33Z

Duplicate of #66

We are aware that the contract allows users to use latent funds, although we disagree on it being an issue as no funds (ERC20 or native) should ever lay in the contract. To make sure that no value is ever kept by the diamond, we now provide refunds for outstanding user value (after bridges/swaps).

Findings Information

🌟 Selected for report: kirk-baird

Also found by: TomFrenchBlockchain, VAD37, WatchPug, hyh, rayn, wuwe1

Labels

bug
duplicate
2 (Med Risk)

Awards

385.2169 USDC - $385.22

External Links

Lines of code

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Libraries/LibSwap.sol#L42 https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/Swapper.sol#L14-L21

Vulnerability details

Proof of Concept

Never use msg.value inside a loop.

  1. LibSwap.swap use msg.value when swapping native assets.

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Libraries/LibSwap.sol#L42

(bool success, bytes memory res) = _swapData.callTo.call{ value: msg.value }(_swapData.callData);
  1. Swapper call LibSwap.swap inside a loop.

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/Swapper.sol#L14-L21

        for (uint8 i; i < _swapData.length; i++) {
            require(
                ls.dexWhitelist[_swapData[i].approveTo] == true && ls.dexWhitelist[_swapData[i].callTo] == true,
                "Contract call not allowed!"
            );

            LibSwap.swap(_lifiData.transactionId, _swapData[i]);
        }
  1. Take GenericSwapFacet as a example

Attacker can call swapTokensGeneric with 1 ether with _swapData.length == 10. This will swap 10 ether to SwapData.callTo.

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/GenericSwapFacet.sol#L22-L30

    function swapTokensGeneric(LiFiData memory _lifiData, LibSwap.SwapData[] calldata _swapData) public payable {
        uint256 receivingAssetIdBalance = LibAsset.getOwnBalance(_lifiData.receivingAssetId);

        // Swap
        _executeSwaps(_lifiData, _swapData);

        uint256 postSwapBalance = LibAsset.getOwnBalance(_lifiData.receivingAssetId) - receivingAssetIdBalance;

        LibAsset.transferAsset(_lifiData.receivingAssetId, payable(msg.sender), postSwapBalance);

Reference

https://samczsun.com/two-rights-might-make-a-wrong/

The amount of native assets to be sent should be specified in _swapData. Check that total amount <= msg.value.

#0 - H3xept

2022-04-11T09:20:45Z

Duplicate of #86

Findings Information

🌟 Selected for report: hickuphh3

Also found by: WatchPug, hyh, rayn, shw, wuwe1

Labels

bug
duplicate
2 (Med Risk)

Awards

499.3553 USDC - $499.36

External Links

Lines of code

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/CBridgeFacet.sol#L150

Vulnerability details

Impact

_startBridge will always fail when sending native token.

Proof of Concept

  1. CBridgeFacet:_startBridge is not sending native asset will calling sendNative

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/CBridgeFacet.sol#L150

ICBridge(bridge).sendNative(
  1. sendNative will revert when msg.value != _amount

https://github.com/celer-network/sgn-v2-contracts/blob/32d3f42a662ff3ad040d855657f732d4dece6e83/contracts/Bridge.sol#L82-L94

    function sendNative(
        address _receiver,
        uint256 _amount,
        uint64 _dstChainId,
        uint64 _nonce,
        uint32 _maxSlippage
    ) external payable nonReentrant whenNotPaused {
        require(msg.value == _amount, "Amount mismatch");
        require(nativeWrap != address(0), "Native wrap not set");
        bytes32 transferId = _send(_receiver, nativeWrap, _amount, _dstChainId, _nonce, _maxSlippage);
        IWETH(nativeWrap).deposit{value: _amount}();
        emit Send(transferId, msg.sender, _receiver, nativeWrap, _amount, _dstChainId, _nonce, _maxSlippage);
    }

Change to

ICBridge(bridge).sendNative{value: msg.value}(

#0 - H3xept

2022-04-11T10:59:56Z

Duplicate of #35

Findings Information

🌟 Selected for report: hyh

Also found by: Dravee, JMukesh, Jujic, peritoflores, shw, sorrynotsorry, wuwe1

Labels

bug
duplicate
2 (Med Risk)

Awards

303.3583 USDC - $303.36

External Links

Lines of code

https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/WithdrawFacet.sol#L31

Vulnerability details

Proof of Concept

src/Facets/WithdrawFacet.sol
31:            payable(sendTo).transfer(_amount);

When withdrawing native token, the withdraw is being handled with aΒ payable.transfer()call.

This is unsafe asΒ transferΒ has hard coded gas budget and can fail.

Whenever the user either fails to implement the payable fallback function or cumulative gas cost of the function sequence invoked on a native token transfer exceeds 2300 gas consumption limit the native tokens sent end up undelivered and the corresponding user funds return functionality will fail each time.

Reference

https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now

Use call() instead, without hardcoded gas limits along with checks-effects-interactions pattern or reentrancy guards for reentrancy protection.

#0 - H3xept

2022-04-08T10:08:17Z

Duplicate of #14

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