Liquid Staking

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

By depositing again, the first account account to queue tokens will be included in the accounts array twice leading to invalid calculations when making a new merkleTree

Summary

By depositing again, the first account to queue tokens will be included in the accounts array twice leading to invalid calculations when making a new Merkle Tree

Description

Depositors can decide to queue their tokens for deposit when not enough depositRoom is available so that their tokens can be deposited later when room becomes available in priorityPool.sol::_deposit.

if (toDeposit != 0) {
if (_shouldQueue) {
_requireNotPaused();
if (accountIndexes[_account] == 0) {
accounts.push(_account);
accountIndexes[_account] = accounts.length - 1;
}
accountQueuedTokens[_account] += toDeposit;
totalQueued += toDeposit;
} else {
token.safeTransfer(_account, toDeposit);
}
}
  • https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/core/priorityPool/PriorityPool.sol#L633C13-L643C14

An issue arise that an account to be added in the accounts array, its value in the accountIndexes[_account] mapping should not be zero, but for the first depositor to queue, his value wil be zero since value are stored by subtracting account.length - 1 so for the first deposit queue:

accounts.length = 1
accounts.length - 1 = 0
accountIndexes[First_Queued_Deposit_Account] = 0

So here is a scenario;
The "First_Queued_Deposit_Account" decides to deposit again, since its accountIndexes[First_Queued_Deposit_Account] is zero, the check if (accountIndexes[_account] == 0) will be true and the First_Queued_Deposit_Account will be push in the accounts array for the second time.

Impact

The impact is that when calculating the account Data in PriorityPool.sol::getAccountDataused to create a new merkle root, since the First_Queued_Deposit_Account is included twice in the accounts array its value will be added to reSDLBalances and queuedBalances twice hence inaccurate data than the truly available amounts will be provided.

uint256[] memory reSDLBalances = new uint256[]();
uint256[] memory queuedBalances = new uint256[]();
//@audit initial account can get twice
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);
  • https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/core/priorityPool/PriorityPool.sol#L466C8-L475C58

Tools Used

Manual Review

Recommendation

Consider saving accountIndexes as the actual new length instead of subtracting one.

Updates

Lead Judging Commences

inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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