Core Contracts

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

Gas Limit Exhaustion and Denial of Service Due to Unchecked Array Length in _distributeToGauges

Summary:

GaugeController.sol

function _distributeToGauges(
GaugeType gaugeType,
uint256 amount
) internal {
uint256 totalTypeWeight = 0;
uint256[] memory gaugeWeights = new uint256[](_gaugeList.length);
uint256 activeGaugeCount = 0;
// First pass: calculate total weight and store gauge weights
for (uint256 i = 0; i < _gaugeList.length; i++) {
address gauge = _gaugeList[i];
if (gauges[gauge].isActive && gauges[gauge].gaugeType == gaugeType) {
gaugeWeights[i] = gauges[gauge].weight;
totalTypeWeight += gaugeWeights[i];
activeGaugeCount++;
}
}
if (totalTypeWeight == 0 || activeGaugeCount == 0) return;
// Second pass: distribute rewards
for (uint256 i = 0; i < _gaugeList.length; i++) {
address gauge = _gaugeList[i];
if (gauges[gauge].isActive && gauges[gauge].gaugeType == gaugeType) {
uint256 gaugeShare = (amount * gaugeWeights[i]) / totalTypeWeight;
if (gaugeShare > 0) {
IGauge(gauge).notifyRewardAmount(gaugeShare);
}
}
}
}

The function _distributeToGauges iterates over the entire _gaugeList twice, which can lead to high gas consumption if the list size becomes large. This is a risk if an external actor can influence the array length, as they can add many elements, causing the function to exceed the gas limit and fail. This could result in a Denial of Service (DoS) attack, where the distribution of rewards becomes impossible.

Vulnerability Details:

Gas Consumption Risk: The function performs two loops over _gaugeList, which can result in high gas costs if the list is large.

External Manipulation: An attacker can increase the list size by adding gauges, potentially leading to excessive gas usage and failed transactions.

Impact:

Denial of Service (DoS): Excessive gas usage can prevent reward distribution from being processed correctly.

Exploitable by Adversaries: An attacker can manipulate the array length to cause the transaction to exceed the block gas limit, disrupting contract operations.

Proof of Concept (PoC):

An attacker could add a large number of gauges to the list, increasing gas usage during the loop:

function attackAddGauges(uint256 numGauges) external {for (uint256 i = 0; i < numGauges; i++) {_gaugeList.push(address(new Gauge())); // Add a large number of gauges}}

Tools Used: none

Recommendations:

Maintain a running total of gauge weights and only iterate over the relevant gauges. You can store a totalTypeWeight and gaugeWeights separately for active gauges to avoid looping through the entire array.

uint256 public totalTypeWeight; // Store total weight of active gauges
function \_distributeToGauges(GaugeType gaugeType, uint256 amount) internal {
uint256 totalTypeWeight = 0;
uint256\[] memory gaugeWeights = new uint256;
uint256 activeGaugeCount = 0;
// Update logic to only loop through active gauges
for (uint256 i = 0; i < _gaugeList.length; i++) {
address gauge = _gaugeList[i];
if (gauges[gauge].isActive && gauges[gauge].gaugeType == gaugeType) {
gaugeWeights[i] = gauges[gauge].weight;
totalTypeWeight += gaugeWeights[i];
activeGaugeCount++;
}
}
// Further logic as before...
}

By ensuring the weight is tracked and updated more efficiently, you eliminate the risk of excessive gas usage.

Updates

Lead Judging Commences

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

GaugeController._distributeToGauges iterates twice over unbounded gauges list without error handling, causing DoS risk from out-of-gas or single gauge revert

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

GaugeController._distributeToGauges iterates twice over unbounded gauges list without error handling, causing DoS risk from out-of-gas or single gauge revert

Support

FAQs

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