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
Rank: 87/185
Findings: 1
Award: $12.29
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: CatsSecurity
Also found by: 0xSmartContract, 0xbrett8571, 0xepley, Bauchibred, KeyKiril, Myd, SAAJ, SBSecurity, Sathish9098, ZanyBonzy, albahaca, clara, digitizeworx, fouzantanveer, foxb868, glcanvas, hunter_w3b, invitedtea, sakshamguruji, unique
12.2949 USDC - $12.29
This analysis reports on the Kelp Dao
contest which is developed as product to stake assets. The assets when staked will be converted to a token named rsETH
. The protocol uses oracle that calculates the exchange rate of assets. It fetches prices from different price oracles for each asset and calculates the total value of assets in the pool.
Every asset is first approve and deposit into strategies, transfer assets back to the LRT deposit pool, and fetch the balance of all assets staked in the eigen layer through this contract.
The staked mechanism is based on fetching the total amount of an asset, and gets the asset amount distribution data among the deposit pool, NDCs, and the Eigen layer.
This section looks at working mechanism of contracts in scope and discussed the workflow for each contract.
ChainlinkPriceOracle contract interacts with Chainlink price feeds to fetch the exchange rate of assets. The contract has a state variable assetPriceFeed
which is mapping from an asset address to a price feed address. getAssetPrice
function fetches the exchange rate of a given asset by calling the latestAnswer function on the Chainlink price feed associated with the asset. updatePriceFeedFor
function checks if the new price feed address is non-zero and then updates the assetPriceFeed mapping.
LRTConfig contract manages various aspects of the application, such as supported assets, deposit limits, and strategies for each asset. Here's a breakdown of its main functionalities. Assets can be added to this list using the addNewSupportedAsset
function and the deposit limit for each asset can be updated using the updateAssetDepositLimit
function.
LRTConfigRoleChecker as an abstract contract handles role checks for a LRT (Liquidity Reward Token) configuration. updateLRTConfig
function updates the lrtConfig state variable and also checks that the provided address is not zero before updating the lrtConfig and emitting the UpdatedLRTConfig event.
LRTDepositPool contract handle depositing of assets into the protocol and the management of node delegators. The contract checks if the asset is supported and if the deposit amount is within the current limit. If the checks pass, the contract transfers the asset from the user to itself and mints a corresponding amount of rsETH
tokens for the user _mintRsETH
function. The amount of rsETH minted is calculated based on the asset amount and the asset's exchange rate from an oracle. It provides distribution of an asset among the deposit pool, node delegator contracts (NDCs), and the eigen layer through getAssetDistributionData
. The getAssetDistributionData
function returns the amount of the asset in the deposit pool, the total amount in all NDCs, and the amount staked in the eigen layer through all NDCs.
LRTOracle contract is used for asset price Fetching by the getAssetPrice
function fetches the price of a given asset by calling the getAssetPrice
function of the asset's price oracle. getRSETHPrice
function calculates the price of RSETH based on the total supply of RSETH and the total amount of ETH in the pool. updatePriceOracleFor
function allows the LRTManager to update the price oracle for a given asset.
NodeDelegator is responsible for managing the depositing of assets into strategies. maxApproveToEigenStrategyManager
function approves the maximum amount of a specific asset to the Eigen Strategy Manager. depositAssetIntoStrategy
function deposits a specific asset into its strategy. The function first retrieves the strategy for the asset from the LRT config, then retrieves the balance of the asset in the contract, and finally calls the depositIntoStrategy
function of the Eigen Strategy Manager with strategy, token and balance.
transferBackToLRTDepositPool
function transfers a specific amount of a specific asset back to the LRT deposit pool. If the transfer fails, it reverts the transaction with a TokenTransferFailed error. getAssetBalances
function fetches the balance of all assets staked in the Eigen layer through this contract. It returns an array of assets and their corresponding balances.
RSETH contract have various functionality like minting, burning, pausing and unpausing. updateLRTConfig
function allows the DEFAULT_ADMIN_ROLE to update the lrtConfig address. It checks that the new address is non-zero, updates the lrtConfig, and emits an UpdatedLRTConfig event. The contract defines roles like MINTER_ROLE
and BURNER_ROLE
which are used to control access to the minting and burning functions respectively.
There are some pitfalls identified in the codebase related to quality of the code which can affect overall smooth working and efficiency of the Kelp Dao
project.
RSETH
contract does not check if the admin or lrtConfigAddr
addresses are valid (non-zero) addresses.getAssetPrice
function uses latestAnswer
from the Chainlink Aggregator contract. This could potentially return stale data if the latest round is not completed yet. It might be better to use getRoundData and handle the case when the round is not completed yet.There exists several instance of controlled mechanism to a single or group of entity which creates clear issue of centralisation for the project which are discussed as below:
NodeDelegator
and LRTDepositPool
contracts, there are functions that handle the depositing and transferring of assets. These functions can only be called by the LRT manager. This centralizes control over the assets in the contract.ChainlinkPriceOracle
contract price feed for each asset can be updated by the LRT manager. This have the potentially to allow for manipulation of asset prices.RSETH
contract there are roles for minting and burning tokens. If these roles are not properly decentralized, it could lead to manipulation of the token supply.LRTConfig
contract have strategies for assets can be assigned only by the admin. This could potentially allow for manipulation of asset strategies.Systemic risk identified for this project is related to risk that a failure in one part of the system could lead to a failure in the entire system. The potential systemic risks identified for project of Kelp Dao
are discussed as below:
The recommendations are mainly made in context of improving the working mechanism of the project and ensure more convenience to the users. The recommendation will also help other developers to understand the codebase and make changes accordingly with standard safe solidity practice. First recommendation is made for instances of utility functions are used across multiple contracts. Consider moving these utility functions into a library. This can help in reducing the overall gas cost and make the code more understandable and easier to manage.
Recommendation is also made for some contracts use revert statements, while others do not. It's recommended to have consistent error handling across all contractsas it will make it easier to debug and understand the code.
There are some comments in the code and it would be beneficial to have more detailed comments explaining the logic of complex functions. This will make the code easier to understand for new developers and help in maintaining the code in the future.
The recommendation is made to effectively use the upgradeability process . It's important to ensure that all state variables are added to the end of the contract to prevent issues with storage layout.
The project use OpenZeppelin's AccessControl
for role-based access control. It's important to review the role assignment and usage of these roles across the contracts to ensure only the necessary permissions are granted and that roles can't be abused.
This analysis provide details on working mechanism, short fall in code quality and the risk identified for the codebase of the Kelp Dao
project. Recommendation is made to improve any short fall that might impact the security and smooth working of the project in the long term.
The time spent on this project is around 25 hours which helps in identified 03 mediums issues that must be addressed to ensure no risk to the funds or workflow of the project exists that may impact the protocol in a negative manner.
025 hours
#0 - c4-pre-sort
2023-11-17T03:05:14Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2023-11-29T19:03:29Z
fatherGoose1 marked the issue as grade-b