Liquid Staking

Stakelink
DeFiHardhatOracle
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Node Timeouts Due to Unbounded Growth of `PriorityPool::accounts`.

Summary

The accounts storage variable in the PriorityPool contract can grow indefinitely, leading to potential node timeouts when accessing data via the getAccounts and getAccountData functions.

Vulnerability Details

As the accounts array expands without limit, applications using node service providers like Alchemy or Infura may face timeouts during data retrieval. While these functions are view functions and don’t incur gas costs, the increasing computational complexity can make requests too burdensome, resulting in some node providers timing out. Consequently, applications might be forced to deploy their own nodes to retrieve necessary data, complicating integration and user experience.

Furthermore, if other contracts interact with the PriorityPool, they risk encountering out-of-gas errors during internal transactions. This limitation could impede integration efforts, making it more challenging for developers to build efficient applications that rely on the PriorityPool.

function _deposit(
address _account,
uint256 _amount,
bool _shouldQueue,
bytes[] memory _data
) internal {
if (poolStatus != PoolStatus.OPEN) revert DepositsDisabled();
uint256 toDeposit = _amount;
// total number of tokens queued for deposit into the staking pool
if (totalQueued == 0) {
uint256 queuedWithdrawals = withdrawalPool.getTotalQueuedWithdrawals();
if (queuedWithdrawals != 0) {
uint256 toDepositIntoQueue = toDeposit <= queuedWithdrawals
? toDeposit
: queuedWithdrawals;
withdrawalPool.deposit(toDepositIntoQueue);
toDeposit -= toDepositIntoQueue;
IERC20Upgradeable(address(stakingPool)).safeTransfer(_account, toDepositIntoQueue);
}
if (toDeposit != 0) {
uint256 canDeposit = stakingPool.canDeposit();
if (canDeposit != 0) {
uint256 toDepositIntoPool = toDeposit <= canDeposit ? toDeposit : canDeposit;
stakingPool.deposit(_account, toDepositIntoPool, _data);
toDeposit -= toDepositIntoPool;
}
}
}
if (toDeposit != 0) {
if (_shouldQueue) {
_requireNotPaused();
if (accountIndexes[_account] == 0) {
@> inserting a new element for each new account that deposits into the PriorityPool
@> even if the account deposits 1 wei
accounts.push(_account);
accountIndexes[_account] = accounts.length - 1;
}
accountQueuedTokens[_account] += toDeposit;
totalQueued += toDeposit;
} else {
token.safeTransfer(_account, toDeposit);
}
}
emit Deposit(_account, _amount - toDeposit, _shouldQueue ? toDeposit : 0);
}
function getAccounts() external view returns (address[] memory) {
return accounts;
}
function getAccountData()
external
view
returns (address[] memory, uint256[] memory, uint256[] memory)
{
uint256[] memory reSDLBalances = new uint256[]();
uint256[] memory queuedBalances = new uint256[]();
for (uint256 i = 0; i < reSDLBalances.length; ++i) {
address account = accounts[i];
reSDLBalances[i] = sdlPool.effectiveBalanceOf(account);
queuedBalances[i] = accountQueuedTokens[account];
}
return (accounts, reSDLBalances, queuedBalances);
}

Impact

Potential timeouts in node providers when fetching data from the getAccounts and getAccountData functions. Additionally, contracts interacting with these functions may struggle to integrate due to excessive gas consumption.

Tools Used

Manual review.

Recommendations

Use pagination to query data. See:

https://programtheblockchain.com/posts/2018/04/20/storage-patterns-pagination/

Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Appeal created

federodes Submitter
12 months ago
inallhonesty Lead Judge
12 months ago
inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.