rsETH (Kelp DAO) technical analysis
Summary
This is a technical analysis of the rsETH asset’s smart contracts and main dependencies.
Disclosure: This is not an exhaustive security review of the asset like the ones done by the Kelp DAO, but an analysis from an Aave technical service provider on different aspects we consider critical to review before a new type of listing. Consequently, like with any security review, this is not an absolute statement that the asset is flawless, only that, in our opinion, we don’t see significant problems with its integration with Aave, apart from different trust points.
Analysis
rsETH is an LRT that accrues rewards from depositing native ETH and LSTs (currently ETHx and stETH) into restaking platforms, such as EigenLayer.
For the context of this analysis, our focus has been on the following aspects, critical for the correct and secure integration with Aave:
- Mechanism to update the exchange rate of the asset for the LST and underlying ETH.
- Access control (ownerships, admin roles) and nature of the entities involved.
- Any miscellaneous aspect of the code we can consider of importance.
General points
- The upgradeability admin of all systems is an OZ Timelock, which has a 10-day time lock and is controlled by a 6-of-8 Gnosis Safe.
- An OZ transparent proxy pattern is used for proxies.
Contracts
The following is a non-exhaustive overview of the main smart contracts involved with rsETH.
rsETH
- The ERC20 token is an OZ Transparent Proxy contract with upgradeability by the general Timelock.
- The
mint()
andburnFrom()
functions are controlled by the LRTDepositPool and LRTWithdrawalManager contracts, respectively. - The contract can be paused by the Kelp Manager, a 2-of-5 Gnosis Safe, and only unpaused by the Kelp Admin, which is a 3-of-5 Gnosis Safe.
- On L2 chains, the rsETH implements the Omnichain Fungible Token (OFT) Standard by LayerZero, allowing token transfer across multiple chains. It works by burning the token on the initial chain whenever an omnichain transfer is initiated and sending a message (via LayerZero) to the destination contract to mint the same amount.
- On L2s, there is also a wrapped version (wrsETH), which serves as a standard reference point for KelpDAO, as the alt rsETH is basically an OFT Token for cross-chain transfers. The alternative rsETH tokens can be exchanged at a 1:1 ratio for the wrsETH token.
LRTConfig
This contract is the central point for system configurations.: it manages the supported LSTs and their caps and protocol fees.
- It’s an OZ Transparent Proxy with upgradeability by the general timelock.
- The access control is shared between a
DEFAULT_ADMIN_ROLE
role held by a 6-of-8 Gnosis Safe and aMANAGER
not set yet. - The
DEFAULT_ADMIN_ROLE
can add assets and their caps configurations by callingaddNewSupportedAsset(asset, depositLimit)
, and it EigenLayer strategy via theupdateAssetStrategy(asset, strategy)
. - The
MANAGER
can update the asset caps by calling theupdateAssetDepositLimit(asset, depositLimit)
.
LRTDepositPool
- An OZ Transparent Proxy contract, which is also the only rsETH minter, is the entry point for depositing native ETH and other LSTs.
- Users can mint rsETH with native ETH by calling
depositETH
and with LSTs (Currently ETHx and stETH) by callingdepositAsset
- The exchange rate of rsETH/ETH (
rsETHPrice
), and others LRTs (assetPrice
) are queried from the LRTOracle. - To calculate the mint amount the
getRsETHAmountToMint()
function is called, which uses the formula:assetAmount * assetPrice / rsETHPrice
. - The underlying funds are delegated to node operators registered in EigenLayer. Currently, the node operator partners are Kiln, Allnodes, Luganodes and Omakase
- The contract can be paused by the Kelp Manager and only unpaused by the Kelp Admin like the rsETH token.
- The LRT Manager can transfer ETH and LSTs to a node delegator, swap ETH for LSTs lying in the deposit Pool, and pause the Pool.
- The LRT Admin can add and remove node delegators to/from the queue, set the minimum amount to deposit, update the maximum number of node delegators, and unpause the Pool.
LRTWithdrawalManager
- The exit point for withdrawal LSTs is an OZ Transparent Proxy contract, which is also the only rsETH burner. Currently, it’s not possible to withdraw native ETH.
- The withdrawals happen in a 2-step process, where users first call
initiateWithdrawal()
entering the withdrawal queue, and between 7-10 days (7-day delay imposed by EigenLayer along with the time required by Kelp to execute withdrawals) the LRT operator will redeem the staked assets for the users finally callcompleteWithdrawal()
. - The LRT Admin can set the minimum amount and the delay interval to withdraw, and unpause the Withdrawal Manager contract.
LRTOracle
- OZ Transparent Proxy contract with upgradeability by the general Timelock.
- The exchange rate is updated permissionless by calling
updateRSETHPrice()
, which is calculated using the formula:staked assets value in ETH / rsETH supply
. - To calculate the staked assets value in ETH is queried each staked asset amount from the depositPool by calling
getTotalAssetDeposits()
, which returns the amount among the Deposit Pool, Node Delegator Contracts, and EigenLayer, then is multiplied by its exchange rate (for LSTs) or 1 (for native ETH). - The
getTotalAssetDeposits()
function internally calls thegetAssetDistributionData(asset)
to obtain the balances via theasset.balanceOf()
function instead of virtual balances, meaning that the exchange rate of rsETH can be manipulated by inflating its price via donation of these assets. - Internally, the
updateRSETHPrice()
calls a_isNewPriceOffLimit(oldPrice, newPrice)
that checks if the price is out of bounds limited by thepricePercentageLimit
storage variable, but currently it’s set to zero.
Asset Pricing
After reviewing the system and its exchange rate calculations, our suggestion for pricing is a CAPO rsETH/ETH exchange rate (fetched from the LRT Oracle) + ETH/USD feed.
It’s important to mention that we identified during the analysis that the exchange rate is prone to manipulation by donating LSTs. The system accounts for LSTs lying in the DepositPool contract using balanceOf
instead of virtual balances.
However, any risks associated with any possible manipulation of the exchange will be minimized during the listing of this asset, giving the following points:
- The rsETH will be listed as non-borrowable, minimizing any well-known attacks on the borrowing side to zero.
- The primary use case for rsETH will be used as collateral in the new e-mode categories implemented in v3.2.
- Like what was described in ezETH (here), any potential donation is considered an injection of rewards and an actual cost and loss to the attacker. Donating LSTs to increase collateral value and borrow more WETH is unlikely to compensate for the cost of the donation, meaning that the attacker gains little to no benefit from this action.
Disclosure: The price strategy in this analysis accounts for only ETH, ETHx, and stETH (the underlying assets currently composing rsETH), and the Kelp Team has confirmed they are not planning to add new ones in the future.
Miscellaneous
- The system has multiple audits by auditors such as Sigma Prime, C4, and MixBytes. We still recommend adding some extra.
- The 10-day Timelock with the 6-9 multi-sig that upgrades the system is solid, as it gives enough time to check all the functionalities being implemented. However, some permissioned functions like
addNewSupportedAsset
are still managed via multi-sig, which we think could be managed via the timelock as an extra security layer, because any underlying asset added could directly affect how rsETH is priced on Aave.
We have recommended the Kelp DAO team to address this. - The lack of methods to off-board underlying assets from rsETH makes the asset pricing not a straightforward process. For example, off-boarding an underlying asset is only possible by setting its caps to zero. If an underlying asset is removed from rsETH, the system would still account for any amount transferred to the DepositPool contract because it uses
balanceOf
, meaning the rsETH is wrongly priced.
We have recommended the Kelp Team to include a function to remove underlying assets from the assets list in the LRTConfig contract so the system would be protected from off-boarded assets lying in the DepositPool contract being accounted in the rsETH price.
Conclusion
From our technical service provider perspective, rsETH seems to have no significant issues with integration into Aave. However, we still have some recommendations, mainly those addressed in Miscellaneous, about how the team manages the onboard/off-board of underlying assets, which would add extra security to this listing.
Additionally, the DAO should be aware that procedures suggested in the asset pricing section must be followed to correct pricing and minimize any risks associated with manipulations.