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

Findings: 3

Award: $2,530.80

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: 0xDjango

Also found by: hake, kirk-baird, rayn, shenwilly

Labels

bug
duplicate
3 (High Risk)

Awards

2219.3568 USDC - $2,219.36

External Links

Lines of code

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

Vulnerability details

Impact

A faulty input in GenericSwapFacet.swapTokensGeneric() could cause funds to get stuck in the contract.

In addition, tokens left in the LiFi contract can be retrieved by anyone (see issue: ERC20 withdrawals can be frontrun), leading to loss of fund.)

Proof of Concept

  1. Alice calls swapTokensGeneric(), inputting WETH as lifiData.receivingAssetId, USDC as swapData.sendingAssetId, and USDT as swapData.receivingAssetId.
  2. The contract swaps Alice's USDC to USDT, but tries to send WETH instead of USDT.
  3. Alice receives nothing and the USDT is now stuck in the contract.

Ensure that lifiData.receivingAssetId is equal to receivingAssetId of the final _swapData.

#0 - itsmetechjay

2022-03-29T14:06:46Z

Updated per warden to link to another issue submitted.

#1 - H3xept

2022-04-11T10:22:29Z

Duplicate of #137

#2 - gzeoneth

2022-04-16T17:49:14Z

Agree with sponsor this does not pose a functional risk. Changing to Low/QA.

#3 - gzeoneth

2022-04-16T19:00:50Z

Consider with #81

#4 - gzeoneth

2022-05-09T21:29:02Z

This should be a duplicate of #75 instead, I made a mistake during the deduplication process.

Findings Information

🌟 Selected for report: hake

Also found by: Jujic, WatchPug, catchup, danb, defsec, kirk-baird, nedodn, shenwilly, sorrynotsorry

Labels

bug
duplicate
2 (Med Risk)
sponsor acknowledged

Awards

196.5762 USDC - $196.58

External Links

Lines of code

https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/DexManagerFacet.sol#L17-L26 https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/GenericSwapFacet.sol#L22-L43

Vulnerability details

Impact

GenericSwapFacet.swapTokensGeneric() can run arbitrary calls on any whitelisted addresses. A malicious/compromised governance can whitelist token contracts and steal funds from users that have given allowance to LiFi contract.

Proof of Concept

  1. Alice approves infinite USDC allowance to LiFi.
  2. Governance calls addDex(), whitelisting USDC contract.
  3. Governance calls swapTokensGeneric() with USDC as the callTo and transferFrom as the callData, stealing Alice's fund.

Recommend using timelock when managing dexWhitelist.

#0 - H3xept

2022-04-12T09:34:49Z

Duplicate of #65

Awards

114.8562 USDC - $114.86

Labels

bug
sponsor acknowledged
QA (Quality Assurance)

External Links

Lines of code

https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Facets/GenericSwapFacet.sol#L22-L43 https://github.com/code-423n4/2022-03-lifinance/blob/699c2305fcfb6fe8862b75b26d1d8a2f46a551e6/src/Libraries/LibSwap.sol#L33-L35

Vulnerability details

Impact

Tokens sent to the contract can be retrieved by anyone, which opens up the possibility for WithdrawFacet.withdraw() to be frontrun.

When swapping ERC20 tokens, LibSwap.swap only tries to transfer tokens if the contract doesn't have enough balance to swap. As long as a market for the token exists, anyone can call GenericSwapFacet.swapTokensGeneric() to swap any token in the contract and retrieve them.

Proof of Concept

  1. Alice mistakenly sent 1000 USDC to LiFi contract.
  2. Governance tries to rescue the USDC by calling WithdrawFacet.withdraw().
  3. An attacker front run the transaction by calling GenericSwapFacet.swapTokensGeneric(), using USDC as sendingAssetId and WETH as receivingAssetId. The attacker receives free WETH.

Consider transferring the token (sendingAssetId of the first _swapData) to the contract before executing the swaps. Return the value of toAmount in LibSwap.swap() and use it as the fromAmount value for the next swap. This way an attacker cannot utilise funds left in the contract for swapping.

#0 - H3xept

2022-04-13T15:15:31Z

By fixing other audit reports, we now have made sure that no value can be left in the contract via swap and bridge methods by refunding any outstanding token.

To our knowledge, the only way a user can transfer value to our contract and have it sit there is to directly send it. We highly discourage this behaviour and we internally decided that such a deliberate action is unlikely. Therefore we believe that it is not worth mitigating, as the necessary checks would increase the transaction costs for all contract calls.

#1 - gzeoneth

2022-04-16T17:48:29Z

Downgrading to Low/QA. Treating as warden's QA Report.

#2 - JeeberC4

2022-04-17T04:20:34Z

Preserving original title: ERC20 withdrawals can be frontrun

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