The Standard

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

Gas griefing by packing pendingStakes & holders arrays

Summary

In LiquidationPool, pendingStakes & holders array can be packed to gas grief and cause DoS for the pool and the runLiquidation function.

Vulnerability Details

Every time a new user stake in the pool, a new PendingStake struct is pushed to the pendingStakes array, and a new holder is added to the holders array:

function increasePosition(uint256 _tstVal, uint256 _eurosVal) external {
require(_tstVal > 0 || _eurosVal > 0);
consolidatePendingStakes();
ILiquidationPoolManager(manager).distributeFees();
if (_tstVal > 0) IERC20(TST).safeTransferFrom(msg.sender, address(this), _tstVal);
if (_eurosVal > 0) IERC20(EUROs).safeTransferFrom(msg.sender, address(this), _eurosVal);
pendingStakes.push(PendingStake(msg.sender, block.timestamp, _tstVal, _eurosVal));
addUniqueHolder(msg.sender);
}

The problem arises as functions distributeFees() and consolidatePendingStakes() iterate through those arrays, leading to increased gas costs with each iteration.

An attacker can exploit this by spamming the pool with multiple accounts, each staking small amounts, causing the arrays to grow excessively. This creates almost empty pending stakes, resulting in an Out of Gas (OOG) error when functions iterate through the arrays. Consequently, the runLiquidation() function becomes prohibitively expensive, potentially causing a revert due to exceeding the gas limit.

runLiquidation
-> distributeFees -> distributeFees -> will iterate through all holders + pendingStakes arrays
-> distributeAssets -> consolidatePendingStakes -> will iterate through all pendingStakes array
-> getStakeTotal -> will iterate through all holders array
-> will iterate through all holders array

Making runLiquidation() so expensive to call and it may revert due to exceeding the block size gas limit.

Impact

The LiquidationPool contract is vulnerable to DoS attacks, where an attacker can use multiple accounts to stake small amounts, causing an Out of Gas error. This results in:

  • The locking of user and liquidation funds within the contract.

  • Critical functions like runLiquidation() will throw due to exceeding the block's gas limit.

Tools Used

Manual review

Recommendations

Consider enforcing a minimum stake amount a maximum array length for both holders and pendingStakes arrays in LiquidationPool to prevent such attacks.

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!