code-423n4 / 2023-11-kelp-findings

13 stars 11 forks source link

The first minter address can mint rsETH up to the current limit with the help of a flashloan, and can also temporarily cause a Denial of Service for other users. #331

Closed c4-submissions closed 11 months ago

c4-submissions commented 11 months ago

Lines of code

https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTDepositPool.sol#L119 https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTOracle.sol#L56

Vulnerability details

Brief/Explanation

The first address to deposit rETH, stETH, or cbETH gets to mint up to the current limit at a 1:1 exchange rate with the help of a flashloan. Additionally, since the threshold of the minting has been reached, he would also have cause a temporary DOS until the manager increases the limit.

Impact

Every user who tries to mint rsETH in exchange for stETH, rETH, or cbETH is subjected to the exchange rate except the first minter. For the sake of this report, we'll call this person ALICE. According to the protocol's design, ALICE can deposit the aforementioned tokens in exchange for rsETH at 1:1 because totalSupply == 0. Taking it up a notch, Alice being the first minter can borrow ETH, stake it to get stETH, and mint up to 100_000 ether rsETH which is the current limit. Doing this will not only allow ALICE to mint an enormous amount of rsETH at 1:1, sell on a secondary market to make profit if possible, she can also cause others to be temporarily unable to mint rsETH until the current limit is raised.

Proof of Concept

    function test__firstDepositIssue() public {
        assertEq(lrtDepositPool.getTotalAssetDeposits(rETHAddress), 0);

        //creates two address, the hacker/first minting address and the other user who will
        //experience the DOS
        address hacker = makeAddr("HACKER");
        address anotherUser = makeAddr("Another User");

        //Flashloan and staking already took place
        deal(rETHAddress, hacker, lrtDepositPool.getAssetCurrentLimit(rETHAddress));
        emit log_named_uint("The rETH balance of the hacker is ", rETH.balanceOf(hacker)/1 ether);

        deal(rETHAddress, anotherUser, 10 ether);
        emit log_named_uint("The rETH balance of the other user is ", rETH.balanceOf(anotherUser)/1 ether);

        vm.startPrank(hacker);
        rETH.approve(address(lrtDepositPool), rETH.balanceOf(hacker));
        lrtDepositPool.depositAsset(rETHAddress, rETH.balanceOf(hacker));
        vm.stopPrank();

        assertEq(rseth.balanceOf(hacker), 100_000 ether);

        //just to also demonstrate how the hacker address can cause temporary dos until the manager increases the limit
        vm.startPrank(anotherUser);
        rETH.approve(address(lrtDepositPool), 10 ether);
        vm.expectRevert();
        lrtDepositPool.depositAsset(rETHAddress, 10 ether);
        vm.stopPrank();
    }

Tools Used

Foundry, Kelp test files, manual Review

Recommendation

Mint at least 1 rsETH token during deployment or initialization to eliminate the first minting opportunity discussed above

Assessed type

Other

c4-pre-sort commented 11 months ago

raymondfam marked the issue as sufficient quality report

c4-pre-sort commented 11 months ago

raymondfam marked the issue as duplicate of #42

c4-pre-sort commented 11 months ago

raymondfam marked the issue as not a duplicate

c4-pre-sort commented 11 months ago

raymondfam marked the issue as duplicate of #338

c4-pre-sort commented 11 months ago

raymondfam marked the issue as duplicate of #879

raymondfam commented 11 months ago

A flash loan exploit would need to be executed atomically. The situation described in multiple separate steps/calls isn't going to work.

c4-judge commented 10 months ago

fatherGoose1 marked the issue as satisfactory

c4-judge commented 10 months ago

fatherGoose1 marked the issue as unsatisfactory: Invalid