Core Contracts

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

Wrong rewards calculation in the `GaugeController::_calculateReward`

Summary

Wrong rewards calculation in the GaugeController::_calculateReward happens due to the wrong assumption that every gauge weight should be included in the calculation of gauge shares

Vulnerability Details

There are 2 types of gauges one being the RWAGauge (Real World Assets gauge) and the second one being the RAACGauge. When the GaugeController::distributeRewards function is called it relies on the _calculateReward function to get the reward that should be distributed to the corresponding gauge. By taking a look into the function, we see a big problem in the following line of code:

function _calculateReward(address gauge) internal view returns (uint256) {
Gauge storage g = gauges[gauge];
@> uint256 totalWeight = getTotalWeight();
if (totalWeight == 0) return 0;
uint256 gaugeShare = (g.weight * WEIGHT_PRECISION) / totalWeight;
uint256 typeShare = (typeWeights[g.gaugeType] * WEIGHT_PRECISION) /
MAX_TYPE_WEIGHT;
// Calculate period emissions based on gauge type
uint256 periodEmission = g.gaugeType == GaugeType.RWA //FIXME: Should be reversed
? _calculateRWAEmission()
: _calculateRAACEmission();
return
(periodEmission * gaugeShare * typeShare) /
(WEIGHT_PRECISION * WEIGHT_PRECISION);
}

The problem is that the getTotalWeight function returns the gauge weight of all of the gauges, without applying a gauge type condition. Lets consider the following example for simplicity:
(we have 3 gauges, 1 RWAGauge and 2 RAACGauges)

  1. The distributeRewards function is called on one of the RAACGauges

  2. Then as of the active state of the code and considering that the 3 gauges have the same weight, the rewards will destributed as it follows:

    • 1/3 for RAACGauge

    • 1/3 for RAACGauge

    • 1/3 for RWAGauge

This means that the RWAGauge gets counted into the RAACGauge reward calculations, lowering the allocations to RAACGauges and being unable to receive it because the allocation for RWAGauge is different. In this case, the RAACGauges will get 2/3 of the weekly allocation they should get, because of the RWAGauge that is accounted in those calculations. It is the same the other way around, which is bad because the different gauges are accounted for the emissions of the other type of gauge

Impact

This will lead to big reward miscalculation in both RWAGauge and RAACGauge and to not the whole monthly and weekly allocations being distributed to the correct gauges

Tools Used

Manual Review

Recommendations

When you get the gauge in the _calculateReward function, get its type and iterate trough the gauges mapping to get all of the active gauges from the same type and extract their weights in the totalWeight variable. From then on the calculation should be the same as the totalWeight now includes the weights of gauges from the corresponding type, rather than the total weight of all gauges

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

GaugeController::_calculateReward uses combined weight of all gauge types instead of type-specific weights, causing incorrect reward distribution between RWA and RAAC gauges

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

GaugeController::_calculateReward uses combined weight of all gauge types instead of type-specific weights, causing incorrect reward distribution between RWA and RAAC gauges

Appeal created

kirobrejka Submitter
4 months ago
inallhonesty Lead Judge
4 months ago
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

GaugeController::_calculateReward uses combined weight of all gauge types instead of type-specific weights, causing incorrect reward distribution between RWA and RAAC gauges

Support

FAQs

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