The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: high
Valid

Unbounded Loop in Consolidating Pending Stakes Disrupts Protocol

[H-03] Unbounded Loop in Consolidating Pending Stakes Disrupts Protocol

Description

A vulnerability within the smart contract allows a malicious user to inflate the LiquidationPool::pendingStakes array excessively. The LiquidationPool::consolidatePendingStakes() function, crucial for increasing, decreasing holders' positions, or distributing assets upon smart vault liquidation, can cause gas exhaustion and revert due to an unbounded loop.

function consolidatePendingStakes() private {
uint256 deadline = block.timestamp - 1 days;
@> for (int256 i = 0; uint256(i) < pendingStakes.length; i++) { // @audit unbounded loop, reverts with high pendingStakes length
PendingStake memory _stake = pendingStakes[uint256(i)];
if (_stake.createdAt < deadline) {
positions[_stake.holder].holder = _stake.holder;
positions[_stake.holder].TST += _stake.TST;
positions[_stake.holder].EUROs += _stake.EUROs;
deletePendingStake(uint256(i));
// Pause iterating on loop because there has been a deletion. "Next" item has the same index
i--;
}
}
}

Impact

The vulnerability in LiquidationPool::consolidatePendingStakes() severely disrupts crucial functionalities of the contract. It affects the increase, decrease of stakes, and asset distribution during liquidation. Consequently, funds can be indefinitely locked within affected smart vaults. This issue not only hampers holders' transactions but also enables malicious borrowers to exploit the protocol by preventing liquidation.

Proof of Concept

  1. Bob creates a smart vault, deposits 10 ETH as collateral, and mints 16000 EUROs.

  2. Bob repeatedly calls LiquidationPool::increasePosition(), continually escalating his position until the function reverts.

  3. A day after Bob's deposits, market volatility causes ETH's price to drop, requiring liquidation of his vault.

  4. A user initiates LiquidationPoolManager::runLiquidation(), triggering LiquidationPool::distributeAssets(). However, the LiquidationPool::consolidatePendingStakes() function reverts due to hitting the block gas limit, rendering Bob's vault inliquidatable.

Recommended Mitigation

Consider improving the consolidation logic for pending stakes or reworking the protocol's logic associated with them. Possible solutions include:

  1. Introduce function parameters like offset and length to divide consolidation into smaller batches.

  2. Implement an upper limit on the number of pending stakes.

Tools Used

Manual Review

Updates

Lead Judging Commences

hrishibhat Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

pendingstake-dos

hrishibhat Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

pendingstake-high

Support

FAQs

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

Give us feedback!