Kelp DAO | rsETH - wisdomn_'s results

A collective DAO designed to unlock liquidity, DeFi and higher rewards for restaked assets through liquid restaking.

General Information

Platform: Code4rena

Start Date: 10/11/2023

Pot Size: $28,000 USDC

Total HM: 5

Participants: 185

Period: 5 days

Judge: 0xDjango

Id: 305

League: ETH

Kelp DAO

Findings Distribution

Researcher Performance

Rank: 107/185

Findings: 2

Award: $7.42

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

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

Vulnerability details

Impact

The first depositor can break minting of rseth. The attack vector and impact is the same as TOB-YEARN-003, where users may not receive shares in exchange for their deposits if the total asset amount has been manipulated through a large “donation”.

    function depositAsset(         address asset,         uint256 depositAmount     )         external         whenNotPaused         nonReentrant         onlySupportedAsset(asset)     {         // checks         if (depositAmount == 0) {             revert InvalidAmount();         }         if (depositAmount > getAssetCurrentLimit(asset)) {             revert MaximumDepositLimitReached();         }         if (!IERC20(asset).transferFrom(msg.sender, address(this), depositAmount)) {             revert TokenTransferFailed();         }

Tools Used

Manual Review

Uniswap V2 solved this problem by sending the first 1000 LP tokens to the zero address. The same can be done in this case i.e. when the totalSupply of rseth == 0, send some of the first tokens to the zero address. This will prevent this attack.

Assessed type

Error

#0 - c4-pre-sort

2023-11-16T02:52:22Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2023-11-16T02:52:56Z

raymondfam marked the issue as duplicate of #42

#2 - c4-judge

2023-12-01T16:59:39Z

fatherGoose1 marked the issue as satisfactory

Awards

2.7592 USDC - $2.76

Labels

bug
downgraded by judge
grade-b
insufficient quality report
QA (Quality Assurance)
duplicate-69
Q-87

External Links

Lines of code

https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTConfig.sol#L94-L104

Vulnerability details

Impact

Users will be unable to deposit assets into the pool If the depsotiLimit is updated to zero, leading to a dos. The vulnerability lies in the fact that the function doesn't check to ensure that the deposit limit isn't being set to zero before updating it. This can lead to a denial of service (dos).

    function updateAssetDepositLimit(         address asset,         uint256 depositLimit     )         external         onlyRole(LRTConstants.MANAGER)         onlySupportedAsset(asset)     {         depositLimitByAsset[asset] = depositLimit;         emit AssetDepositLimitUpdate(asset, depositLimit);     }

Proof of Concept

A PoC to test the vulnerability. Run forge test to test the PoC. The test will show users unable to deposit due to the vulnerability.

// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.21; import { BaseTest } from "./BaseTest.t.sol"; import { LRTDepositPool } from "src/LRTDepositPool.sol"; import { RSETHTest, ILRTConfig, UtilLib, LRTConstants } from "./RSETHTest.t.sol"; import { ILRTDepositPool } from "src/interfaces/ILRTDepositPool.sol"; import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; contract LRTOracleMock { function getAssetPrice(address) external pure returns (uint256) { return 1e18; } function getRSETHPrice() external pure returns (uint256) { return 1e18; } } contract MockNodeDelegator { function getAssetBalance(address) external pure returns (uint256) { return 1e18; } } contract LRTDepositPoolTest is BaseTest, RSETHTest { LRTDepositPool public lrtDepositPool; function setUp() public virtual override(RSETHTest, BaseTest) { super.setUp(); // deploy LRTDepositPool ProxyAdmin proxyAdmin = new ProxyAdmin(); LRTDepositPool contractImpl = new LRTDepositPool(); TransparentUpgradeableProxy contractProxy = new TransparentUpgradeableProxy( address(contractImpl), address(proxyAdmin), "" ); lrtDepositPool = LRTDepositPool(address(contractProxy)); // initialize RSETH. LRTCOnfig is already initialized in RSETHTest rseth.initialize(address(admin), address(lrtConfig)); vm.startPrank(admin); // add rsETH to LRT config lrtConfig.setRSETH(address(rseth)); // add oracle to LRT config lrtConfig.setContract(LRTConstants.LRT_ORACLE, address(new LRTOracleMock())); // add minter role for rseth to lrtDepositPool rseth.grantRole(rseth.MINTER_ROLE(), address(lrtDepositPool)); vm.stopPrank(); } } contract LRTDepositPoolGetAssetCurrentLimit is LRTDepositPoolTest { address public rETHAddress; function setUp() public override { super.setUp(); // initialize LRTDepositPool lrtDepositPool.initialize(address(lrtConfig)); rETHAddress = address(rETH); // add manager role within LRTConfig vm.startPrank(admin); lrtConfig.grantRole(LRTConstants.MANAGER, manager); vm.stopPrank(); } function test_DosDeposit() external { vm.startPrank(manager); lrtConfig.updateAssetDepositLimit(address(stETH), 0 ether); vm.stopPrank(); // deposit 1 ether stETH vm.startPrank(alice); stETH.approve(address(lrtDepositPool), 6 ether); lrtDepositPool.depositAsset(address(stETH), 6 ether); vm.stopPrank(); assertEq(lrtDepositPool.getAssetCurrentLimit(address(stETH)), 4 ether, "Asset current limit is not set"); } }

Tools Used

Manual Review and Foundry.

Check to ensure that the depositLimit of an asset isn't zero when updating the depositLimit

Assessed type

DoS

#0 - c4-pre-sort

2023-11-16T03:30:37Z

raymondfam marked the issue as insufficient quality report

#1 - c4-pre-sort

2023-11-16T03:30:56Z

raymondfam marked the issue as duplicate of #69

#2 - c4-judge

2023-11-29T20:58:12Z

fatherGoose1 changed the severity to QA (Quality Assurance)

#3 - c4-judge

2023-11-29T21:01:33Z

fatherGoose1 marked the issue as grade-b

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