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: 146/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
https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTDepositPool.sol#L184 https://github.com/code-423n4/2023-11-kelp/blob/f751d7594051c0766c7ecd1e68daeb0661e43ee3/src/LRTDepositPool.sol#L162-L163
The node delegator is added by the LRTAdmin
by calling addNodeDelegator
the new nodeDelegatorContract
is pushed into the nodeDelegatorQueue
array which can later be used by the LRTManager
to deposit assets on EigenLayer.
However there are a few potential problems with the addNodeDelegator
function..
1- nodeDelegatorContracts
can be pushed into the array and they can't be popped this cause an issue where a nodeDelegatorContract
gets taken over by a malicious user and it can't be removed.
However unlikely It can be more significant because of the different access roles to the functions if the LRTAdmin
which is in charge of calling the addNodeDelegatorContract
function adds a malicious contract due to human error or the nodeDelegatorContract
gets taken over the LRTManager
which is in charge of calling the transferAssetToNodeDelegator
might still procced by sending assets to such contract which will lead to loss of users asset.
2-No existence check on the nodeDelegatorContract
being added.
The same nodeDelegatorContract
can represent multiple array indexes, when LRTManager
calls transferAssetToNodeDelegator
to transfer assets the nodeDelegatorContract
is represented by it's index in nodeDelegatorQueue[ndcIndex]
.
If a nodeDelegatorContract
is represented multiple times in the array it can potentially lead to confusion for the users and a possible misplace of asset into a different strategy.
For example
function addNodeDelegatorContractToQueue(address[] calldata nodeDelegatorContracts) external onlyLRTAdmin { uint256 length = nodeDelegatorContracts.length; if (nodeDelegatorQueue.length + length > maxNodeDelegatorCount) { revert MaximumNodeDelegatorCountReached(); } for (uint256 i; i < length;) { UtilLib.checkNonZeroAddress(nodeDelegatorContracts[i]); nodeDelegatorQueue.push(nodeDelegatorContracts[i]);
addNodeDelegator
adds a new nodeDelegatorContract
without checking if it already exists in the array, adding the same nodeDelegatorContract
of the same address in different indexes.
Also due to the fact that there's no way to remove a nodeDelegatorContract
the array indexes will not be in order, a contract address might be represented twices or more in the index.
LRTManager
might call transferAssetToNodeDelegator
with the wrong index.
function transferAssetToNodeDelegator( uint256 ndcIndex, address asset, uint256 amount ) external nonReentrant onlyLRTManager onlySupportedAsset(asset) { address nodeDelegator = nodeDelegatorQueue[ndcIndex]; if (!IERC20(asset).transfer(nodeDelegator, amount)) { revert TokenTransferFailed(); }
Manual Review
Add a remove function for the nodeDelegatorContract
and an existence check for the newly added nodeDelegatorContract
Invalid Validation
#0 - c4-pre-sort
2023-11-16T01:11:34Z
raymondfam marked the issue as insufficient quality report
#1 - c4-pre-sort
2023-11-16T01:11:47Z
raymondfam marked the issue as duplicate of #38
#2 - c4-judge
2023-12-01T17:45:49Z
fatherGoose1 changed the severity to QA (Quality Assurance)
#3 - c4-judge
2023-12-01T17:46:51Z
fatherGoose1 marked the issue as grade-b