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

4 stars 4 forks source link

Malicious users can steal their locked LRT back by inserting their own token as an intermediary #62

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/main/src/PrelaunchPoints.sol#L413

Vulnerability details

Impact

Prelaunch contract loses their locked LRT (to be appointed as locked ETH), and malicious users effectively stealing their locked LRT back.

Description

Taken from written details about the Points Program in loopfi's documentation.
Link to documentation

The purpose of this program is to acquire liquidity in ETH, using points given to users who lock their ETH as incentives.
After epoch 1 is concluded (convertAllETH() is called), all native ETH are converted to lpETH but not LRT (or other supported tokens).

The unwritten invariance here is that All assets, value in ETH, must all be converted to lpETH (as close to 1:1 as possible, depending on slippage of the swap)
If the above invariance breaks (e.g. only 50% of assets value in ETH are converted to lpETH), the protocol will take the loss since it gives point to users for nothing.

This invariance holds in the case of native ETH since all of native ETH are converted immediately in convertAllETH().
https://github.com/code-423n4/2024-05-loop/blob/main/src/PrelaunchPoints.sol#L321-L324

However, this is not always the case for other tokens, because those tokens are swapped to native ETH inside claim() then convert to lpETH.
IF there exists an execeution path that would result in less native ETH sent back from swap and (0 is also possible) being converted to lpETH and malicious users still get their locked ETH back in full, then the invariance above wil break.

Looking further into swap parameters that are user-controllable.
https://github.com/code-423n4/2024-05-loop/blob/main/src/PrelaunchPoints.sol#L413

We can clearly see that users calling claim() can control both path and mimimum output amount of the swap.
The minimum output is there to protect users' loss from slippage, however, this is a double-edge sword if we take the above invariance into account.
Malicious users can set minimum output to zero and set the path of swap like this:
[LRT, MALICIOUS, WETH]
Where they set the price of their MALICIOUS token incredibly high in LRT/MALICIOUS pool and very low in MALICIOUS/WETH pool.
Using this swap path, these malicious users can effectively transfer their locked LRT to their pool and return 0 WETH to prelaunch contract.

The prelaunch contract would lose locked LRT, and these malicious users still get point from locking LRT in Epoch 1

Proof-of-Concept

I added a new test function to demonstrate that malicious users can steal their locked LRT back by inserting their fake token as intermediary in swap path.
Steps

  1. apply below git diff in 2024-05-loop repository

    
    diff --git a/test/PrelaunchPoints.t.sol b/test/PrelaunchPoints.t.sol
    index 753d3ef..3c3f693 100644
    --- a/test/PrelaunchPoints.t.sol
    +++ b/test/PrelaunchPoints.t.sol
    @@ -13,6 +13,44 @@ import {LRToken} from "../src/mock/MockLRT.sol";
    
    import "forge-std/console.sol";

+interface IFactory{

Tools used

Assessed type

Other

c4-judge commented 4 months ago

koolexcrypto marked the issue as primary issue

0xd4n1el commented 4 months ago

This is possible, but for the points program we use Claim event too, so you cannot farm points without actually getting your tokens converted into lpETH

c4-judge commented 3 months ago

koolexcrypto marked the issue as duplicate of #66

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