Core Contracts

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

Reward accounting is a mess due to `_getBaseWeight` getting weight for the gauge and not the user

Summary

Reward accounting is a mess due to _getBaseWeight getting weight for the gauge and not the user

Vulnerability Details

Users rewards are calculated with earned, which in order to get what each user deserves needs to first get their proportions of the staking token/veToken.

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/governance/gauges/BaseGauge.sol#L583

function earned(address account) public view returns (uint256) {
// 10k * (rewardPerTokenGlobal - rewardPerTokenUser) / 1e18
return (getUserWeight(account) *
(getRewardPerToken() - userStates[account].rewardPerTokenPaid) / 1e18
) + userStates[account].rewards;
}

For that it calls ``getUserWeight, which in theory will get the user wight. However in practice it gets the gauge weight instead, as _getBaseWeightcallgetGaugeWeight(address(this))`

https://github.com/Cyfrin/2025-02-raac/blob/main/contracts/core/governance/gauges/BaseGauge.sol#L594

function getUserWeight(address account) public view virtual returns (uint256) {
//@audit `getUserWeight` - but this is not the user weight ? it's the contract
// IGaugeController(controller).getGaugeWeight(address(this))
uint256 baseWeight = _getBaseWeight(account);
function _getBaseWeight(address account) internal view virtual returns (uint256) {
return IGaugeController(controller).getGaugeWeight(address(this));
}

Impact

User weights are misconfiguration, their rewards too.
Internal accounting is broken.
First users will claim huge rewards and the rest won't be able to claim any. That is because every user weight is gonna be about the same.

Tools Used

Manual review

Recommendations

Consider changing _getBaseWeight to

function _getBaseWeight(address account) internal view virtual returns (uint256) {
- return IGaugeController(controller).getGaugeWeight(address(this));
+ return IGaugeController(controller).getGaugeWeight(account);
}
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!