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: 130/185
Findings: 1
Award: $2.76
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
onlySupportedAsset()
is missing in getAssetBalance()
https://github.com/code-423n4/2023-11-kelp/blob/main/src/NodeDelegator.sol#L121-L124
The method getAssetBalance()
doesn't check if the asset is a supportedAsset or not. Which can revert or will return wrong values if assetStrategy is present for that asset.
Add onlySupportedAsset()
modifier in getAssetBalance()
method
- function getAssetBalance(address asset) external view override returns (uint256) { + function getAssetBalance(address asset) external view override onlySupportedAsset(asset) returns (uint256) { address strategy = lrtConfig.assetStrategy(asset); return IStrategy(strategy).userUnderlyingView(address(this)); }
https://github.com/code-423n4/2023-11-kelp/blob/main/src/LRTOracle.sol#L45-L47
The getAssetPrice()
returns to price of an asset by fetching in from Chainlink oracle. It checks onlySupportedAsset()
modifier but doesn't check if the price feed for this asset is present or not.
The getAssetPrice()
doesn't check if the price feed for the asset is added. It can revert unexpectedly when calculating RSETH or asset prices.
function getAssetPrice(address asset) external view onlySupportedAsset(asset) returns (uint256) { return AggregatorInterface(assetPriceFeed[asset]).latestAnswer(); }
_mintRsETH()
https://github.com/code-423n4/2023-11-kelp/blob/main/src/LRTDepositPool.sol#L151-L157
The method _mintRsETH()
mint and sends RSETH to the caller. But the check rsethAmountToMint != 0 is missing in the function.
if(rsethAmountToMint == 0) { revert("RSETH amount is 0"); }
Add the following test in ChainlinkPriceOracleTest.t.sol
contract ChainlinkPriceOracleFetchAssetPriceMissingPriceFeed is ChainlinkPriceOracleTest { MockPriceAggregator public priceFeed; function setUp() public override { super.setUp(); priceOracle.initialize(address(lrtConfig)); priceFeed = new MockPriceAggregator(); vm.prank(manager); } function test_FetchAssetPriceWithMissingPriceFeed() external { vm.expectRevert(); priceOracle.getAssetPrice(address(rETH)); } }
Handle missing price feed expection gracefully
function getAssetPrice(address asset) external view onlySupportedAsset(asset) returns (uint256) { - return AggregatorInterface(assetPriceFeed[asset]).latestAnswer(); + address priceFeed = assetPriceFeed[asset]; + if(priceFeed == address(0)) { + revert("Missing price feed"); + } + return AggregatorInterface(priceFeed).latestAnswer(); }
LRTConfig
contractUpdate the comment as below:
/// @param cbETH cbETH address - /// @param rsETH_ cbETH address + /// @param rsETH_ rsETH_ address
https://github.com/code-423n4/2023-11-kelp/blob/main/src/LRTConfig.sol#L19 https://github.com/code-423n4/2023-11-kelp/blob/main/src/LRTConfig.sol#L135-L137
Pubic variable supportedAssetList can be set as private. Because there is a getter present in the contract.
address[] private supportedAssetList;
#0 - c4-pre-sort
2023-11-17T23:36:17Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2023-12-01T18:48:33Z
fatherGoose1 marked the issue as grade-b