The BaseGauge contract’s reward distribution mechanism is critically flawed. The reward calculation fails to incorporate a user’s staked balance due to an incorrect implementation in the weight computation logic. Specifically, the _getBaseWeight
function erroneously uses the contract’s own gauge weight (via address(this)
) instead of the user’s stake. This oversight enables any user—even those with zero staked tokens—to claim rewards, thereby bypassing the intended economic commitment required for earning rewards.
Incorrect Base Weight Derivation:
The earned
function, which computes the rewards for an account, is defined as:
This function calls getUserWeight(account)
, which in turn depends on:
Instead of using the account
parameter to derive a user-specific base weight, the function incorrectly calls getGaugeWeight
with address(this)
. As a result, every user is assigned the same base weight—one that is based solely on the gauge weight of the contract itself.
Lack of Staked Balance Consideration:
In a properly functioning staking system, the rewards should scale with the staked tokens, typically involving a calculation along the lines of:
However, by not incorporating the staked balance (tracked in _balances
), the reward distribution is decoupled from user contributions. Consequently, a user with no staked tokens can still claim rewards, since the gauge weight used is a property of the contract rather than the user’s participation.
Bypassing Economic Incentives:
Due to the error, users are incentivized to exploit the system by repeatedly calling the getReward
function—even if they have never staked any tokens—thereby draining the reward pool without any actual commitment or risk.
Scenario Setup:
Deploy the BaseGauge contract along with its dependencies (staking token, reward token, veToken, and GaugeController).
Ensure multiple user accounts are available.
Exploit Steps:
Step 1: From Account A, do not call the stake
function (thus, _balances[Account A] remains zero).
Step 2: Allow the contract to accumulate rewards (or simulate a reward accrual period).
Step 3: From Account A, call the getReward
function.
Observation:
Despite having no staked tokens, Account A successfully claims rewards.
This happens because the reward calculation uses a base weight derived from address(this)
(the contract) instead of the user’s own stake.
Result:
Account A receives rewards proportionate to the gauge weight of the contract, illustrating that staking is effectively bypassed
Unfair Reward Distribution:
Users can claim rewards without staking any tokens, meaning that rewards are not allocated based on actual economic participation. This undermines the fundamental design of the staking mechanism.
Economic Exploitation:
Malicious actors can abuse the flaw to continuously claim rewards, depleting the reward pool and potentially destabilizing the protocol's incentive structure. This results in an erosion of the value proposition for genuine stakers.
Loss of Protocol Integrity:
The integrity of the staking mechanism is compromised, leading to inaccurate reward calculations. Over time, such discrepancies can diminish stakeholder confidence, reduce user engagement, and negatively affect the long-term viability of the system.
Revenue Drain:
As rewards are distributed without proper staking contributions, the protocol may incur unexpected financial losses, thereby affecting its sustainability and market reputation.
Manual review
Correct the Base Weight Calculation:
Modify the _getBaseWeight
function to incorporate the user’s staked balance. For instance, if the design intends for the base weight to reflect the staked amount, the function should be updated as follows:
Alternatively, if the design mandates that gauge weight is a factor, the function should correctly reference the user’s address:
Integrate Staked Balance into User Weight Calculation:
Adjust the getUserWeight
function so that it properly factors in the staked balance. For example:
This ensures that rewards are proportional to the actual staked tokens and any additional multipliers.
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.