LoopFi - bbl4de's results

A dedicated lending market for Ethereum carry trades. Users can supply a long tail of Liquid Restaking Tokens (LRT) and their derivatives as collateral to borrow ETH for increased yield exposure.

General Information

Platform: Code4rena

Start Date: 01/05/2024

Pot Size: $12,100 USDC

Total HM: 1

Participants: 47

Period: 7 days

Judge: Koolex

Id: 371

League: ETH

LoopFi

Findings Distribution

Researcher Performance

Rank: 28/47

Findings: 1

Award: $71.11

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

71.1111 USDC - $71.11

Labels

bug
3 (High Risk)
partial-25
sufficient quality report
upgraded by judge
:robot:_42_group
edited-by-warden
duplicate-33

External Links

Lines of code

https://github.com/code-423n4/2024-05-loop/blob/0dc8467ccff27230e7c0530b619524cc8401e22a/src/PrelaunchPoints.sol#L249 https://github.com/code-423n4/2024-05-loop/blob/0dc8467ccff27230e7c0530b619524cc8401e22a/src/PrelaunchPoints.sol#L262

Vulnerability details

Impact

When claimedAmount is calculated in the (_token == ETH) branch, the amount of lpETH received may be greater than the staked ETH in case there was an accidental direct deposit of ETH to the contract. The user making this transfer of ETH rightfully losses it without a way to recover, the issue is that the ETH can be considered to be lost as much as it would be when sent to a dummy address, as there is no way to recover it from the contract - you can only recover ERC20s or use the withdraw() function as a user. The excess balance causes totalLpETH to be greater than totalSupply because of the following lines in convertAllETH:

uint256 totalBalance = address(this).balance;
lpETH.deposit{value: totalBalance}(address(this));
totalLpETH = lpETH.balanceOf(address(this));

Therefore, it increases the claimedAmount for each user. This is causing the conversion rate between ETH and lpETH to not equal 1. Moreover, considering the (_token != ETH) branch, a user can _fillQuote with amount equal to userClaim, however the claimedAmount can be increased by simply sending ETH directly to the contract right before the call to claim() or claimAndStake() functions. Again, this makes the conversion to change from 1:1, because ETH sent directly to the contract is NOT accessible by anyone including the owner.

Both of these situations make the lpETH inflationary as users essentially get more lpETH for the same amount of real stake if they do what's explained above for both _claim() function token branches.

Proof of Concept

To run a PoC proving how the received lpETH is indeed increased when the user sends ETH directly to the contract right before calling claim() change the code in PrelaunchPoints0x.test.ts to the code in this gist and run the test with yarn hardhat test ./test/PrelaunchPoints0x.test.ts.

Tools Used

Manual Review, Hardhat

To mitigate this issue consider changing the approach from push to pull, meaning that in convertAllETH the owner does not deposit all ETH to the lpETH contract. Thanks to this, totalSupply and totalLpETH variables can be removed and the user gets the appropriate amount of lpETH based on their share of the contract's balance.

Assessed type

Token-Transfer

#0 - c4-judge

2024-05-15T14:16:12Z

koolexcrypto marked the issue as duplicate of #18

#1 - c4-judge

2024-06-03T09:03:32Z

koolexcrypto changed the severity to 3 (High Risk)

#2 - c4-judge

2024-06-05T07:29:36Z

koolexcrypto changed the severity to 2 (Med Risk)

#3 - c4-judge

2024-06-05T09:29:29Z

koolexcrypto marked the issue as partial-50

#4 - c4-judge

2024-06-05T09:41:00Z

koolexcrypto changed the severity to 3 (High Risk)

#5 - c4-judge

2024-06-05T09:41:19Z

koolexcrypto marked the issue as duplicate of #33

#6 - c4-judge

2024-06-11T07:24:06Z

koolexcrypto marked the issue as partial-25

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