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: 52/185
Findings: 2
Award: $78.78
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: crack-the-kelp
Also found by: 0xDING99YA, 0xffchain, Aymen0909, Bauchibred, DanielArmstrong, Pechenite, Stormy, T1MOH, ZanyBonzy, ast3ros, bLnk, chaduke, crack-the-kelp, deepkin, deth, jasonxiale, jayfromthe13th, lsaudit, nmirchev8, osmanozdemir1, roleengineer, tallo, zhaojie
76.0163 USDC - $76.02
https://github.com/Layr-Labs/eigenlayer-contracts/blob/75e59432d079c6f90d48d4e950a68c15867c82b2/src/contracts/core/StrategyManager.sol#L237-L251 https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTConfig.sol#L108-L122
A copy of each strategy for an asset is stored in the LRTConfig contract, This copy of the asset to strategy mapping allows for the updating of a strategy mapped to an asset in updateAssetStrategy
. It is also of note that the contract does not allow an already supported asset to be unsupported. But a once supported strategy could be updated for another new strategy as specified in the code.
function updateAssetStrategy( address asset, address strategy ) external onlyRole(DEFAULT_ADMIN_ROLE) onlySupportedAsset(asset) { UtilLib.checkNonZeroAddress(strategy); if (assetStrategy[asset] == strategy) { revert ValueAlreadyInUse(); } assetStrategy[asset] = strategy; }
The challenge with this is that when a deposit is made to a strategy, and the strategy is swapped for another new one, it means that the deposits made to the previous strategy is now un-redeemable as it is no more in the system anywhere again.
Strategy mapped to CbETH has about 200 CbETH stored in it on the Eigen Layer and 50 CbEth on the NDC.
There is a vulnerability on CbEth strategy specifically or on CbEth protocol and EigenLayer removes the Strategy from strategyIsWhitelistedForDeposit
from its codebase
The admin/manager on Kelp has two options, either to pause the entire contract cause of one strategy vulnerability or remove that strategy and update to a new one which the EigenLayer will deploy.
If the admin goes for the second, it then means that deposits to the strategy is now trapped. This should not be the case as even EigenLayer only disables deposits and not deposits and withdrawal.
Admin might also choose to both pause the contract and update the strategy, as the strategy update like other setters on config isn't pause protected.
Manual
Should not allow for updating of strategy explicitly rather create a mechanism to disable a strategy for deposit only.
Other
#0 - c4-pre-sort
2023-11-16T23:32:44Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-11-16T23:32:55Z
raymondfam marked the issue as duplicate of #197
#2 - c4-judge
2023-12-01T17:24:51Z
fatherGoose1 marked the issue as unsatisfactory: Invalid
#3 - c4-judge
2023-12-08T17:26:43Z
fatherGoose1 marked the issue as satisfactory
๐ Selected for report: m_Rassska
Also found by: 0x1337, 0xAadi, 0xHelium, 0xLeveler, 0xblackskull, 0xbrett8571, 0xepley, 0xffchain, 0xluckhu, 0xmystery, 0xrugpull_detector, 0xvj, ABAIKUNANBAEV, Aamir, AerialRaider, Amithuddar, Bauchibred, Bauer, CatsSecurity, Cryptor, Daniel526, Draiakoo, Eigenvectors, ElCid, GREY-HAWK-REACH, Inspecktor, Juntao, King_, LinKenji, Madalad, MaslarovK, Matin, MatricksDeCoder, McToady, Noro, PENGUN, Pechenite, Phantasmagoria, RaoulSchaffranek, SBSecurity, SandNallani, Shaheen, Soul22, Stormreckson, T1MOH, Tadev, TeamSS, TheSchnilch, Topmark, Tumelo_Crypto, Udsen, Yanchuan, ZanyBonzy, _thanos1, adeolu, adriro, alexfilippov314, almurhasan, amaechieth, anarcheuz, ayden, baice, bareli, boredpukar, bronze_pickaxe, btk, cartlex_, catellatech, chaduke, cheatc0d3, circlelooper, codynhat, crack-the-kelp, critical-or-high, debo, deepkin, desaperh, dipp, eeshenggoh, evmboi32, ge6a, gesha17, glcanvas, gumgumzum, hals, hihen, hunter_w3b, jasonxiale, joaovwfreire, ke1caM, leegh, lsaudit, marchev, merlinboii, niser93, osmanozdemir1, paritomarrr, passion, pep7siup, phoenixV110, pipidu83, poneta, ro1sharkm, rouhsamad, rvierdiiev, sakshamguruji, seerether, shealtielanz, soliditytaker, spark, squeaky_cactus, stackachu, supersizer0x, tallo, taner2344, turvy_fuzz, twcctop, ubl4nk, wisdomn_, xAriextz, zach, zhaojie, zhaojohnson, ziyou-
2.7592 USDC - $2.76
As https://blog.openzeppelin.com/secure-smart-contract-guidelines-the-dangers-of-price-oracles/ mentions, "multisigs can immediately block access to price feeds at will" When this occurs, executing AggregatorInterface(assetPriceFeed[asset]).latestAnswer()
will revert so calling the getAssetPrice
functions also revert, which cause denial of service when calling functions like depositAsset
for depositing funds into the protocol, cause now assets cannot be priced to allow minting of rETH tokens, This will DOS the protocol and limits its intended use.
Chainlink oracle data feed is used for getting the LSD token's price.
Bob calls the depositAsset function to deposit into the pool and Mint rETH.
Chainlink's multisigs suddenly blocks access to price feeds so executing AggregatorInterface(assetPriceFeed[asset]).latestAnswer();
will revert.
Bob Tries again to perform the intended action and it keeps reverting due to the previous action on chainlink multisigs.
Manual
Oz recommends "https://blog.openzeppelin.com/secure-smart-contract-guidelines-the-dangers-of-price-oracles/" "Therefore, to prevent denial of service scenarios, it is recommended to query ChainLink price feeds using a defensive approach with Solidityโs try/catch structure. In this way, if the call to the price feed fails, the caller contract is still in control and can handle any errors safely and explicitly"
The Oracle contract's getAssetPrice
functions can be updated to refactor ``AggregatorInterface(assetPriceFeed[asset]).latestAnswer();into
try AggregatorInterface(assetPriceFeed[asset]).latestAnswer() returns (int256 answer) { ... } catch Error(string memory) { ... }.` The logic for getting the asset token's price from the Chainlink oracle data feed should be placed in the try block while some fallback logic when the access to the Chainlink oracle data feed is denied should be placed in the catch block. This Fallback logic could be an alternative oracle like uniswap v3, using the twap price.
DoS
#0 - c4-pre-sort
2023-11-17T00:12:47Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-11-17T00:12:56Z
raymondfam marked the issue as duplicate of #32
#2 - c4-pre-sort
2023-11-17T04:45:17Z
raymondfam marked the issue as not a duplicate
#3 - c4-pre-sort
2023-11-17T04:45:23Z
raymondfam marked the issue as primary issue
#4 - c4-pre-sort
2023-11-17T07:34:11Z
raymondfam marked the issue as duplicate of #723
#5 - c4-judge
2023-12-01T17:38:31Z
fatherGoose1 changed the severity to QA (Quality Assurance)