DepositPool is susceptible to the inflation attack #819
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-42
satisfactory
satisfies C4 submission criteria; eligible for awards
sufficient quality report
This report is of sufficient quality
upgraded by judge
Original issue severity upgraded from QA/Gas by judge
Lines of code
https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTDepositPool.sol#L119
Vulnerability details
Summary
The DepositPool contract is susceptible to the Inflation Attack, in which the first depositor can be front-runned by an attacker to steal their deposit.
Impact
The DepositPool pool contract acts mainly as a vault: accounts deposit LST assets and get back RSETH tokens (a share) that represents their participation in the vault.
These types of contracts are potentially vulnerable to the inflation attack: an attacker can front-run the initial deposit to the vault to inflate the value of a share and render the front-runned deposit worthless.
The mint amount in the pool is given by the
getRsETHAmountToMint()
function:https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTDepositPool.sol#L95-L111
While the
getRSETHPrice()
is determined by the asset balance in the contracts:https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTOracle.sol#L52-L79
An attacker can then mint a minimal amount of shares by depositing just 1 token of any valid asset, and then inflate the price per share by donating assets to the deposit pool. Once the share price has been inflated, the front-runned deposit is rounded down to zero or a very small number of shares, causing a loss of funds to the depositor as any precision loss will be captured by the attacker's shares.
Proof of Concept
For simplicity, let's say that the current Chainlink stETH/ETH price is 1 (
1e18
).(amount * lrtOracle.getAssetPrice(asset)) / lrtOracle.getRSETHPrice() = 1 * 1e18 / 1e18 = 1
RSETH.X + 1
.lrtOracle.getRSETHPrice()
will be calculated using the sum of balances of stETH (there are no other assets in the deposit pool),(X + 1) * 1e18 / 1 = (X + 1) * 1e18
. The minted amount is then calculated asX * 1e18 / (X + 1) * 1e18 = X / (X + 1) = 0
. The user is minted 0 RSETH and the deposited amount belongs to the attacker's share.Recommendation
There are multiple ways to prevent the inflation attack:
There are multiple ways of solving the issue:
A very good discussion of these can be found here.
Assessed type
Other
The text was updated successfully, but these errors were encountered: