code-423n4 / 2024-05-loop-findings

4 stars 4 forks source link

Break in Main invariants : Report on Distortion of LPETH to ETH Conversion Ratio #52

Closed howlbot-integration[bot] closed 3 months ago

howlbot-integration[bot] commented 4 months ago

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#L315-L324 https://github.com/code-423n4/2024-05-loop/blob/0dc8467ccff27230e7c0530b619524cc8401e22a/src/PrelaunchPoints.sol#L388-L392

Vulnerability details

Impact

The identified issue in the contract results in a distortion of the conversion ratio between LPETH and ETH, deviating from the intended 1:1 ratio specified in the project documentation. This distortion occurs when users forward ETH directly to the contract, causing the LPETH to ETH conversion ratio to become inaccurate. Such discrepancies breaks one of the contract's main variant.

Proof of Concept

The root cause of the issue lies in the convertAllETH() function, particularly the line:

  function convertAllETH() external onlyAuthorized onlyBeforeDate(startClaimDate) {
        if (block.timestamp - loopActivation <= TIMELOCK) {
            revert LoopNotActivated();
        }

        // deposits all the ETH to lpETH contract. Receives lpETH back
   >>     uint256 totalBalance = address(this).balance;
        lpETH.deposit{value: totalBalance}(address(this));

        totalLpETH = lpETH.balanceOf(address(this));
 /**
     * Enable receive ETH
     * @dev ETH sent to this contract directly will be locked forever.
     */
  >>  receive() external payable {}
 function _claim(address _token, address _receiver, uint8 _percentage, Exchange _exchange, bytes calldata _data)
        internal
        returns (uint256 claimedAmount)
    {
        uint256 userStake = balances[msg.sender][_token];
        if (userStake == 0) {
            revert NothingToClaim();
        }
        if (_token == ETH) {
>> userStake.mulDiv(totalLpETH, totalSupply);

This line of code distorts the conversion ratio between LPETH and ETH when users forward ETH directly to the contract, as it calculates the claimed amount based on a formula that does not adhere to the 1:1 conversion ratio specified in the project documentation.

Users that deposit ETH/WETH get the correct amount of lpETH on claim (1 to 1 conversion) https://code4rena.com/audits/2024-05-loopfi#top:~:text=Users%20that%20deposit%20ETH/WETH%20get%20the%20correct%20amount%20of%20lpETH%20on%20claim%20(1%20to%201%20conversion)

Tools Used

Manual code analysis

Recommended Mitigation Steps

To rectify the distortion of the LPETH to ETH conversion ratio and maintain consistency with the project documentation, the following mitigation steps are recommended:

Direct Withdrawal for User Stake: Allow for direct withdrawal of user stake without the need for intermediate conversions, thereby preserving the 1:1 conversion ratio between LPETH and ETH.

 if (_token == ETH) {
      --    claimedAmount = userStake.mulDiv(totalLpETH, totalSupply);
      ++    claimedAmount = userStake
            balances[msg.sender][_token] = 0;
            lpETH.safeTransfer(_receiver, claimedAmount);

Assessed type

Other

c4-judge commented 4 months ago

koolexcrypto marked the issue as duplicate of #18

c4-judge commented 3 months ago

koolexcrypto changed the severity to 3 (High Risk)

c4-judge commented 3 months ago

koolexcrypto changed the severity to 2 (Med Risk)

c4-judge commented 3 months ago

koolexcrypto marked the issue as not a duplicate

c4-judge commented 3 months ago

koolexcrypto changed the severity to QA (Quality Assurance)

c4-judge commented 3 months ago

koolexcrypto marked the issue as grade-c