Core Contracts

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

BaseGauge::earned returns zero for all user rewards

Summary

The getUserWeight() function in the BaseGauge contract incorrectly calculates user rewards by using the wrong address in earned(). The function uses address(this) instead of the user's address, resulting in zero rewards being returned for all users regardless of their actual earned amounts.

Vulnerability Details

The vulnerability exists in the getUserWeight(account) function. This is called in the earned() function which is called when the reward is updated for an account via updateReward modifier. Instead of using the provided account parameter to determine the user's weight, the function erroneously retrieves the weight for address(this) (the BaseGauge contract itself). Since the contract does not earn rewards, this always returns 0, causing the earned() function to return 0 for all users.

This is particularly critical because:

  1. The contract's weight will always be 0 as it's not meant to earn rewards

  2. The actual user's weight is never considered in the calculation

  3. This effectively breaks the entire reward distribution mechanism

Impact

This vulnerability has severe implications for the protocol:

  • Users cannot receive their earned rewards

  • The reward distribution system is non-functional

  • All calls to check earned rewards will return 0, regardless of the user's actual earned amount

  • This could lead to permanent loss of rewards for users who have staked their tokens

Proof of Concept

The following test demonstrates that the earned() function always returns 0, even after time has passed and rewards should have accumulated for the user. Place this test case within "Reward distribution" of BaseGauge.test.js

it("should calculate earned rewards", async () => {
await network.provider.send("evm_increaseTime", [7 * 24 * 60 * 60]);
await network.provider.send("evm_mine");
const earned = await baseGauge.earned(user1.address);
expect(earned).to.be.eq(0); }); // no rewards earned although

The test shows that even after 7 days (simulated using evm_increaseTime), the earned rewards for the user are still 0.

Recommendation

Modify the getUserWeight() function to correctly use the provided account parameter when being called by earned()

solidity
function _getBaseWeight(address account) internal view virtual returns (uint256) {
- return IGaugeController(controller).getGaugeWeight(address(this));
+ return IGaugeController(controller).getGaugeWeight(account);
}

This ensures that the correct user's weight is used in the reward calculation, allowing for proper reward distribution.

Updates

Lead Judging Commences

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

BaseGauge._getBaseWeight ignores account parameter and returns gauge's total weight, allowing users to claim rewards from gauges they never voted for or staked in

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

BaseGauge._getBaseWeight ignores account parameter and returns gauge's total weight, allowing users to claim rewards from gauges they never voted for or staked in

Support

FAQs

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

Give us feedback!