Open c4-submissions opened 1 year ago
raymondfam marked the issue as sufficient quality report
raymondfam marked the issue as primary issue
Could have used one of the LST's in the POC instead of USDC.
raymondfam marked the issue as high quality report
gus-staderlabs marked the issue as disagree with severity
We agree this is an issue. We also agree that it should be of a MEDIUM severity as it is an edge case that happens on the first protocol interaction.
manoj9april (sponsor) confirmed
Judging as HIGH. While it is an edge case, the potential loss of funds is present. Vault donation attacks have been judged as high in the majority of contests where no safeguards are implemented.
fatherGoose1 marked the issue as satisfactory
fatherGoose1 marked the issue as selected for report
Initial minting is a way of mitigating this issue. And this mitigation could be done after deployment. Hence no safeguard were added in contract. Hence request to decrease to medium.
Initial minting is a way of mitigating this issue. And this mitigation could be done after deployment. Hence no safeguard were added in contract. Hence request to decrease to medium.
Based on the implementation, this issue will remain HIGH. Funds are at risk until Kelp takes subsequent action to mitigate.
Lines of code
https://github.com/code-423n4/2023-11-kelp/blob/c5fdc2e62c5e1d78769f44d6e34a6fb9e40c00f0/src/LRTDepositPool.sol#L95-L110 https://github.com/code-423n4/2023-11-kelp/blob/c5fdc2e62c5e1d78769f44d6e34a6fb9e40c00f0/src/LRTOracle.sol#L52-L79
Vulnerability details
Impact
The first staker can potentially manipulate the price of rsETH through a donation attack, causing subsequent stakers to receive no rsETH after depositing. The first staker can exploit this method to siphon funds from other users.
Proof of Concept
The mining amount of rsETH is calculated in function
getRsETHAmountToMint
which directly utilizes the total value of the asset divided by the price of a single rsETH.Subsequently, the price of rsETH is related to its totalSupply and the total value of deposited assets.
The total value of deposited assets comprises three parts: the assets in
LRTDepositPool
, the assets inNodeDelagator
, and the assets in the eigenlayer. Anyone can directly contribute asset tokens toLRTDepositPool
orNodeDelegator
to augment the total value of deposited assets.Case
Therefore, the price of rsETH is susceptible to manipulation by the first staker, considering the following scenario:
test/LRTDepositPoolTest.t.sol
and run withforge test --match-test test_ControlPrice -vv
.import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import "forge-std/console.sol";
contract LRTOracleMock { function getAssetPrice(address) external pure returns (uint256) {
return 1e18;
return 1; }
function getRSETHPrice() external pure returns (uint256) { @@ -109,6 +110,23 @@ contract LRTDepositPoolDepositAsset is LRTDepositPoolTest { lrtDepositPool.depositAsset(rETHAddress, 2 ether); }
function test_ControlPrice() external {
vm.startPrank(alice);
// alice balance of rsETH before deposit
uint256 aliceBalanceBefore = rseth.balanceOf(address(alice));
rETH.approve(address(lrtDepositPool), 1 ether);
lrtDepositPool.depositAsset(rETHAddress, 1 ether);
// alice balance of rsETH after deposit
uint256 aliceBalanceAfter = rseth.balanceOf(address(alice));
vm.stopPrank();
console.log(" rsETH of Alice: ", aliceBalanceAfter - aliceBalanceBefore);
}
function test_DepositAsset() external { vm.startPrank(alice);
LRTDepositPool
to inflate the price of rsETH. Now the price of rsETH is: (10000 + 1)ether / 1 wei = 10001 etherrsethAmountToMint
is (10000 ether * 1) / (10001)ether = 0Moreover, there is no check on the actual amount of rsETH received by the user, and the execution continues even if this amount is zero.
Tools Used
Manual Review
Recommended Mitigation Steps
It is recommended to pre-mint some rsETH tokens to prevent price manipulation or ensure that the
rsethAmountToMint
is greater than zero.Assessed type
Invalid Validation