Kelp DAO | rsETH - Matin's results

A collective DAO designed to unlock liquidity, DeFi and higher rewards for restaked assets through liquid restaking.

General Information

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

Kelp DAO

Findings Distribution

Researcher Performance

Rank: 174/185

Findings: 1

Award: $2.76

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

2.7592 USDC - $2.76

Labels

bug
downgraded by judge
grade-b
insufficient quality report
QA (Quality Assurance)
duplicate-36
Q-36

External Links

Lines of code

https://github.com/code-423n4/2023-11-kelp/blob/main/src/LRTDepositPool.sol#L162

Vulnerability details

Impact

Duplicate nodeDelegator contract addresses can lead to wrong distribution data in the contract LRTDepositPool

Proof of Concept

The function addNodeDelegatorContractToQueue() is responsible for adding the nodeDelegator contract addresses to the nodeDelegatorQueue array. This will then be used for distribution data in this contract. As we can see in the function addNodeDelegatorContractToQueue():

    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]);
            emit NodeDelegatorAddedinQueue(nodeDelegatorContracts[i]);
            unchecked {
                ++i;
            }
        }
    }

This function doesn't check the duplicate nodeDelegatorContracts[i] and just checks the mentioned address not be a zero address. In the case of providing duplicate and repetitive node delegator contract addresses mistakenly by the admin, these addresses would be added to the mentioned array. Now, If we look at the function getAssetDistributionData(), we can notice that the return amount would be non-accurate:

    function getAssetDistributionData(address asset)
        public
        view
        override
        onlySupportedAsset(asset)
        returns (uint256 assetLyingInDepositPool, uint256 assetLyingInNDCs, uint256 assetStakedInEigenLayer)
    {
        // Question: is here the right place to have this? Could it be in LRTConfig?
        assetLyingInDepositPool = IERC20(asset).balanceOf(address(this));

        uint256 ndcsCount = nodeDelegatorQueue.length;
        for (uint256 i; i < ndcsCount;) {
            assetLyingInNDCs += IERC20(asset).balanceOf(nodeDelegatorQueue[i]);
            assetStakedInEigenLayer += INodeDelegator(nodeDelegatorQueue[i]).getAssetBalance(asset);
            unchecked {
                ++i;
            }
        }
    }

As it is clearly seen, the three return amounts of this function would be wrong due to recalculation of the balance of a nodeDelegatorQueue[i] if there would be duplicates of this address.

Tools Used

Manual Review

Consider checking the nodeDelegatorContracts[i] in the function addNodeDelegatorContractToQueue() before passing the address to the array nodeDelegatorQueue.

Assessed type

Invalid Validation

#0 - c4-pre-sort

2023-11-16T21:11:58Z

raymondfam marked the issue as insufficient quality report

#1 - c4-pre-sort

2023-11-16T21:12:06Z

raymondfam marked the issue as duplicate of #36

#2 - c4-judge

2023-11-29T21:35:51Z

fatherGoose1 changed the severity to QA (Quality Assurance)

#3 - c4-judge

2023-11-29T21:44:02Z

fatherGoose1 marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter