Stader Labs - trustOne's results

Decentralized ETH liquid staking protocol with 4 ETH bond for anyone to be a node operator.

General Information

Platform: Code4rena

Start Date: 02/06/2023

Pot Size: $100,000 USDC

Total HM: 15

Participants: 75

Period: 7 days

Judge: Picodes

Total Solo HM: 5

Id: 249

League: ETH

Stader Labs

Findings Distribution

Researcher Performance

Rank: 21/75

Findings: 1

Award: $857.93

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: Aymen0909

Also found by: T1MOH, bin2chen, trustOne

Labels

bug
2 (Med Risk)
satisfactory
duplicate-341

Awards

857.9344 USDC - $857.93

External Links

Lines of code

https://github.com/code-423n4/2023-06-stader/blob/main/contracts/PoolUtils.sol#L49-L65 https://github.com/code-423n4/2023-06-stader/blob/main/contracts/PoolUtils.sol#L281-L288

Vulnerability details

Impact

The role of the updatePoolAddress function is to update the address of a pool.

However, when attempting to update an existing pool, the function does not behave correctly and consistently reverts with the error message ExistingOrMismatchingPoolId().

Proof of Concept

The issue lies within the verifyNewPool function that is part of the updatePoolAddress function. https://github.com/code-423n4/2023-06-stader/blob/main/contracts/PoolUtils.sol#L49-L65

/** * @notice Update the address of a pool. * @dev This function should only be called by the `DEFAULT_ADMIN_ROLE` role * @param _poolId The Id of the pool to update. * @param _newPoolAddress The updated address of the pool. */ function updatePoolAddress(uint8 _poolId, address _newPoolAddress) external override onlyExistingPoolId(_poolId) onlyRole(DEFAULT_ADMIN_ROLE) { UtilLib.checkNonZeroAddress(_newPoolAddress); verifyNewPool(_poolId, _newPoolAddress); poolAddressById[_poolId] = _newPoolAddress; emit PoolAddressUpdated(_poolId, _newPoolAddress); }

https://github.com/code-423n4/2023-06-stader/blob/main/contracts/PoolUtils.sol#L281-L288

function verifyNewPool(uint8 _poolId, address _poolAddress) internal view { if ( INodeRegistry(IStaderPoolBase(_poolAddress).getNodeRegistry()).POOL_ID() != _poolId || isExistingPoolId(_poolId) ) { revert ExistingOrMismatchingPoolId(); } }

This function checks the validity of the pool ID and pool address, ensuring that they do not already exist.

However, in the case of the updatePoolAddress function, it expects the pool ID to already exist, causing the isExistingPoolId(_poolId) check to always return true.

Consequently, the function consistently reverts with the error message ExistingOrMismatchingPoolId().

Tools Used

To address this issue, you can modify the code by removing the usage of the verifyNewPool function and implementing the following mitigation code:

function updatePoolAddress(uint8 _poolId, address _newPoolAddress) external override onlyExistingPoolId(_poolId) onlyRole(DEFAULT_ADMIN_ROLE) { UtilLib.checkNonZeroAddress(_newPoolAddress); require(poolAddressById[_poolId] != _newPoolAddress, "New address is the same as the current address"); require(INodeRegistry(IStaderPoolBase(_newPoolAddress).getNodeRegistry()).POOL_ID() == _poolId, "Mismatching Pool ID") // Update the pool address poolAddressById[_poolId] = _newPoolAddress; emit PoolAddressUpdated(_poolId, _newPoolAddress); }

Assessed type

Invalid Validation

#0 - c4-judge

2023-06-12T12:52:51Z

Picodes marked the issue as duplicate of #341

#1 - c4-judge

2023-07-02T10:03:55Z

Picodes marked the issue as satisfactory

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