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: 3/59
Findings: 4
Award: $6,234.50
π Selected for report: 0
π Solo Findings: 0
π Selected for report: 0xDjango
Also found by: GeekyLumberjack, pmerkleplant
https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/NXTPFacet.sol#L165
A token swap via NXTPFacet::swapAndCompleteBridgeTokensViaNXTP
in which the receiving amount of tokens is zero does not fail.
The function NXTPFacet::swapAndCompleteBridgeTokensViaNXTP
does not require that the token balance after the swap is higher than the token balance before the swap (see line 165).
Add a require statement checking that postSwapBalance - startingBalance > 0
after the _executeSwap
call.
#0 - H3xept
2022-04-06T14:41:13Z
Fixed in lifinance/lifi-contracts@87a27cee2fbde337c4ab873971f37573d2240994
#1 - H3xept
2022-04-11T11:46:47Z
Duplicate of #76
π Selected for report: hake
Also found by: Kenshin, Ruhum, VAD37, WatchPug, csanuragjain, hickuphh3, hyh, kirk-baird, obront, pmerkleplant, rayn, shw, tintin, wuwe1
77.3842 USDC - $77.38
https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Libraries/LibSwap.sol#L33 https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/AnyswapFacet.sol#L76
Any ERC20 token balance held in the contract can be stolen by an attacker.
The swap
function in the LibSwap.sol
library checks if the contract's balance is sufficient to execute the trade (see line 33).
If the contract does not hold the number of tokens to swap, the amount is transferred from the caller to the contract.
As long as the swap
function is called with a swap amount of a token being less than the balance of the token in the contract, the function does not transfer the tokens from the caller but uses the contract's own tokens for the swap.
Furthermore, as the swapData
argument is created by the caller (see for example AnyswapFacet.sol
line 76), the contract called could be controlled by the caller and statically only returning 1 arbitrary token.
Remove the second condition in the if-clause in the LibSwap::swap
function to always transfer the tokens from the caller to the contract before executing a swap.
#0 - H3xept
2022-04-12T08:38:40Z
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).
π Selected for report: hyh
Also found by: danb, kirk-baird, pmerkleplant
https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/NXTPFacet.sol#L133
A user wanting to bridge ERC20 tokens would lose all ETH accidentally send to the contract.
The bridging facets follow the pattern of checking if the token is native or ERC20.
In case the token is ERC20, there is no check that msg.value == 0
(except for NXTPFacet::completeBridgeTokensViaNXTP
).
This leads to the ETH sent accidentally by a user being held unaccounted for in the contract and being lost for the user.
Refactor following functions to include a check that msg.value == 0
in case the token address is not zero:
CBridgeFacet::startBridgeTokensViaCBridge
CBridgeFacet::swapAndStartBridgeTokenViaCBridge
AnyswapFacet::startBridgeTokensViaAnyswap
AnyswapFacet::swapAndStartBridgeTokensViaAnyswap
NXTPFacet::swapAndStartBridgeTokensViaNXTP
NXTPFacet::swapAndStartBridgeTokensViaAnyswap
HopFacet::swapAndStartBridgeTokensViaHop
HopFacet::startBridgeTokensViaHop
#0 - H3xept
2022-04-11T12:47:57Z
π Selected for report: shw
Also found by: Picodes, hickuphh3, hyh, pmerkleplant
https://github.com/code-423n4/2022-03-lifinance/blob/main/src/Facets/CBridgeFacet.sol#L68
A user wanting to bridge ETH via CBridge could lose some amount of ETH.
The function startBridgeTokenViaCBridge
checks the amount of ETH transfered with msg.value >= _cBridgeData.amount
in case the token address is zero.
If a user accidentally sends more ETH than _cBridgeData.amount
, that ETH would be held unaccounted for in the contract and be lost for the user.
Refactor the check to msg.value == _cBridgeData.amount
.
#0 - H3xept
2022-04-06T08:19:34Z
Fixed in previous commit.
#1 - H3xept
2022-04-11T11:17:07Z
Duplicate of #207