Liquid Staking

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

Merkle Tree Index Validation Bug in PriorityPool Contract

Summary

A critical bug has been identified in the withdraw function of the PriorityPool smart contract, specifically related to the validation logic that compares a user's Merkle tree index with the size of the Merkle tree (merkleTreeSize). This issue causes incorrect rejection of valid users during withdrawal attempts. The bug stems from an incorrect validation condition that triggers a revert when a user's index is smaller than the tree size. A correct validation procedure is observed in the unqueueTokens function, but this logic is improperly applied in withdraw, creating a security vulnerability that could prevent users from withdrawing their tokens. According to the project documentation, "Yes, you can withdraw your LINK from the Priority Pool at any time"​, making the bug a violation of intended contract functionality.

Vulnerability Details

The core issue lies in the validation logic of the withdraw function. Here’s the problematic code snippet:

else if (accountIndexes[account] < merkleTreeSize) {
revert InvalidProof();
}

In this logic, if the user’s accountIndexes[account] is less than the merkleTreeSize, the transaction is reverted with an InvalidProof error. However, according to the Merkle Tree design and the system's documentation, if a user's index is less than the tree size, it signifies that the user is part of the current valid Merkle tree and thus their tokens should be withdrawable.

The correct logic can be seen in the unqueueTokens function:

if (accountIndexes[account] < merkleTreeSize) {
bytes32 node = keccak256(
bytes.concat(keccak256(abi.encode(account, _amount, _sharesAmount)))
);
if (!MerkleProofUpgradeable.verify(_merkleProof, merkleRoot, node)) {
revert InvalidProof();
}
}

In this function, the same comparison between accountIndexes[account] and merkleTreeSize is performed, but instead of directly reverting, the function goes on to verify the Merkle proof. Only if the proof is invalid does it revert the transaction. This is the correct approach, as it ensures that users who are part of the current tree can withdraw their tokens, provided their Merkle proof is valid.

Impact

This vulnerability results in a denial of service for legitimate users. Any user whose index is less than the merkleTreeSize will incorrectly be blocked from withdrawing their tokens from the pool. Given that accountIndexes[account] < merkleTreeSize should indicate that the user is part of the valid Merkle tree, the current logic incorrectly prevents valid withdrawals.

Tools Used

Manually

Recommendations

Replace the current incorrect comparison logic with the correct validation used in the unqueueTokens function.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

[INVALID] Merkle Tree Index Validation asymmetry between unqueueTokens and withdraw inside PriorityPool

Appeal created

galturok Judge
about 1 year ago
demorextess Judge
about 1 year ago
0xsurena Submitter
about 1 year ago
demorextess Judge
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

[INVALID] Merkle Tree Index Validation asymmetry between unqueueTokens and withdraw inside PriorityPool

Support

FAQs

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