BaseGauge.sol
In typical gauge or reward distribution contracts, a user’s staked token balance influences how many rewards they earn. However, BaseGauge calculates the user’s reward weight as follows:
Key Observations:
No Use of _balances[account]
The contract tracks staked tokens in _balances[account], updated by stake(...) and withdraw(...), but _getBaseWeight never references _balances[...].
Global Instead of User-Specific
_getBaseWeight(account) simply calls getGaugeWeight(address(this)) on the gauge controller, returning a single gauge-wide figure, ignoring how many tokens that user staked.
Reward Computations
The user’s “weight” is multiplied by (getRewardPerToken() - userStates[account].rewardPerTokenPaid) to compute earned(account). So if _getBaseWeight(account) is the same for everyone (or entirely ignoring staked amounts), the user’s actual stake is not factored into their share of rewards.
Staking Has No Effect
Users can stake huge amounts of stakingToken in the gauge, but it won’t increase getUserWeight(...) or earned(...). The gauge effectively disregards each user’s staked balance, awarding rewards based on the gauge’s global weight from the controller plus a possible “veRAAC” boost.
User Surprise or Loss
A user who invests heavily, expecting a proportional share of rewards, will discover the contract’s reward logic does not consider their staked tokens. This can lead to confusion or feelings of a “broken” gauge system.
Design Contradiction
The code calls stake(...)/withdraw(...) and manages _totalSupply plus _balances[account], implying a typical “stake to earn” pattern. But because _getBaseWeight(account) never references _balances[account], the actual “stake to earn” flow is not implemented.
A minimal demonstration:
No matter how many tokens userA or userB stake, they get the same base weight if the gauge controller’s weight is constant.
Incorporate _balances[account]
A typical gauge uses a user’s staked token share to determine reward distribution. For instance, rename _getBaseWeight(account) to something that multiplies or references _balances[account].
Document/Remove Unused Staking
If the gauge design only relies on veRAAC for distribution (and not the staked stakingToken amounts), remove or clarify the entire “stake/withdraw” logic. Right now, it confuses integrators into believing it’s standard “stake to earn.”
Align with Child Contract
If _getBaseWeight(account) is meant to be overridden by child contracts to factor in _balances[account], explicitly mention that in the doc. Possibly:
or a combination of gauge weight and user stake.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.