Closed c4-submissions closed 11 months ago
raymondfam marked the issue as sufficient quality report
raymondfam marked the issue as duplicate of #62
fatherGoose1 marked the issue as satisfactory
fatherGoose1 changed the severity to 2 (Med Risk)
fatherGoose1 changed the severity to 3 (High Risk)
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/LRTDepositPool.sol#L136
Vulnerability details
Users will receive less
RSETH
tokens when depositing into the contract usingLRTDepositPool::deposit(...)
. The function transfers the deposit tokens to itself and then makes calculation for the amount ofRSETH
to be minted for the user. Because of this token transfer to self before the calculation for the mint, the users will get less tokens then actual amount.Impact
The
LRTDepositPool::deposit(...)
function makes call to different functions from the same contract that again calls other contracts to calculate the amount of token to mint for the user. Here is a high level flow:This function makes a call to
LRTDepositPool::getAssetDistributionData()
(indirectly) to fetch the total amount of tokens deposited inLRTDepositPool
,NodeDelegator
and Eigen Layer strategies. To fetch the assets deposited inLRTDepositPool
thisLRTDepositPool::getAssetDistributionData()
function perform the following operation:Github: 79
This just reads the balance of the
asset
thatLRTDepositPool
has. Now the problem is, when user callsLRTDepositPool::deposit()
, this function first transfer the tokens to itself and then calls_mintRsETH()
to calculate the amount ofRSETH
to mint to the user.Github: 136-138,141
But when a call reaches to
LRTDepositPool::getAssetDistributionData()
, the function calculate theassetLyingInDepositPool
using the above operation that just reads the balance of token that is stored inLRTDepositPool
usingERC20::balanceOf()
function. But this balance now also stores the newly added tokens as they were transferred to this contract in the beginning. That means the data inassetLyingInDepositPool
will be more than it should be. This amount will be returned back toLRTOracle::getRSETHPrice()
after going through some other functions that will add this amount to balance oftoken
stored inNodeDelegator
and Eigen Layer strategies.Github: 70-71
This
totalAssetAmt
contains all amount of a token that is stored in different contracts that also includes the newly deposited amount. Then this amount will be multiplied with corresponding ETH price feed and will be stored intotalETHInPool
. Now when theRSETH
price is returned from the function it will be in ratio of total eth deposited in pools to the total supply ofRSETH
. And since theRSETH
supply will be less than the total deposits of eth stored intotalETHInPool
because the correspondingRSETH
has not been minted yet. the ratio returned will be more than expected. This ratio will increase if theamount
provided toLRTDepositPool::deposit(...)
is increased.Now this ratio will be returned to the
LRTDepositPool::getRsETHAmountToMint()
and it will perform the following calculation:Github: 95-110
This ratio returned is in the denominator of the calculation that means the bigger this ratio is and the lesser will be
rsethAmountToMint
. And thisrsethAmountToMint
is the actual amount ofRSETH
token that will be minted to the user. So bigger the deposit by the user, the lesser the tokens he will receive.Proof of Concept
Test for Poc
Link to the original test: Test
Output
As you can see the
RSETH
minted was equal to the token deposited in the first deposit only because theRSETH
supply was 0 at that time andLRTOracle::getRSETHPrice(...)
function has this check that ensures that the ratio will be1 ether
in case the supply ofRSETH
is zero:Github: 56
So the ratio of token minted by token deposited in second transaction becomes =
250 / 500 = 0.5
. Or we can say for each token deposit we got back0.5 RSETH
.The mint amount get lesser when bigger amount of tokens are deposited. Here is a test that proves that:
Link to original Test: 373
Output:
As you can can see for 500 tokens we got 500
RSETH
initially and for 20000 tokens we got only487 RSETH
approx. So the ratio of token minted by token deposited becomes =487 / 20000 = 0.02 approx
. Or we can say for each token deposit we got0.02 RSETH
.Tools Used
Recommended Mitigation Steps
It is recommended to add the following check after the minting function:
Assessed type
Other