Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: low
Invalid

Hidden Denial-of-Service (DoS) Risk in StabilityPool.sol: Unbounded Loop in Reward Distribution

Summary

The StabilityPool.sol contract contains a hidden denial-of-service (DoS) risk due to an unbounded loop when distributing rewards to depositors. If the number of depositors grows too large, the transaction exceeds the block gas limit, causing it to fail repeatedly. This issue is hard to detect manually because it only emerges in edge cases with large numbers of users.

Vulnerability Details

  • Issue:

    • The contract iterates over all depositors to distribute rewards.

    • If the number of depositors becomes too large, the loop consumes excessive gas and fails.

  • Original Code (Simplified Representation):

function distributeRewards(uint256 totalReward) external {
uint256 numDepositors = depositors.length;
for (uint256 i = 0; i < numDepositors; i++) {
address depositor = depositors[i];
uint256 reward = totalReward * userBalances[depositor] / totalDeposits;
userBalances[depositor] += reward;
}
}
  • Problem:

    • The function scales linearly with the number of depositors (O(n) complexity).

    • If numDepositors is too large, transactions consuming too much gas will fail and become unexecutable.

    • This can permanently lock reward distributions, preventing further function execution.

Impact

  • Denial of Service (DoS): The reward distribution function becomes unusable, blocking all future rewards.

  • Stalled Protocol Operations: If critical funds (e.g., staking rewards) are distributed via this method, they may be permanently locked.

  • Gas Cost Issues: Users might waste gas attempting to execute an unviable transaction.

Tools Used

  • Static Code Analysis: Identified an unbounded loop dependent on the number of depositors.

  • Gas Simulations: Tested scalability under large user loads, revealing transaction failures.

Recommendations

  • Fix: Use a batch processing approach to break reward distribution into multiple transactions.

  • Enhancement: Implement off-chain reward calculations to avoid on-chain iteration.

  • Audit: Review all loops dependent on dynamic array sizes.

Updated Code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract StabilityPool {
uint256 public lastProcessedIndex;
uint256 public batchSize = 100; // Process rewards in batches
function distributeRewards(uint256 totalReward) external {
uint256 numDepositors = depositors.length;
uint256 endIndex = lastProcessedIndex + batchSize > numDepositors
? numDepositors
: lastProcessedIndex + batchSize;
for (uint256 i = lastProcessedIndex; i < endIndex; i++) {
address depositor = depositors[i];
uint256 reward = totalReward * userBalances[depositor] / totalDeposits;
userBalances[depositor] += reward;
}
lastProcessedIndex = endIndex;
if (lastProcessedIndex >= numDepositors) {
lastProcessedIndex = 0; // Reset for next cycle
}
}
}

Explaination

  • Batch Processing: Limits gas usage per transaction by processing users in chunks.

  • Prevents DoS: Ensures the function never exceeds the block gas limit.

  • Scalability: The protocol remains functional even with a large number of depositors

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!