governance -> boost -> BoostController.sol -> Line 177
The updateUserBoost
function calculates a user’s boost using a fixed base amount (10000) instead of a dynamically derived value from the user’s current veToken balance or voting power. It then directly assigns this boost value to the pool’s working supply rather than aggregating boosts across users. This approach may lead to inaccurate pool metrics and reward distribution errors.
Fixed Base Amount Issue:
The function calls:
This fixed base value does not adapt to real-time changes in the user’s veToken holdings.
Pool Update Logic:
The pool’s workingSupply
is directly overwritten:
This design does not aggregate boosts from all users and can lead to miscalculations if multiple user boosts are updated separately.
Reward Distribution Errors:
Incorrect boost calculations can lead to improper reward allocations.
Manipulation Potential:
Users might time balance changes to benefit from the fixed calculation mechanism.
Inconsistent Pool Metrics:
The working supply may not accurately represent the collective boost state, leading to systemic errors in rewards or fee calculations.
The following test demonstrates that when the user’s veToken balance increases, the updated boost value increases—but the fixed base amount in the calculation does not allow for a truly dynamic recalculation.
We deploy a DummyGauge contract (DummyGauge.sol) as the pool, ensuring that a valid, non‑null gauge address is passed. Also, we no longer call setVotingPower since our MockVeToken does not implement it.
import pkg from "hardhat";
const { ethers } = pkg;
import { expect } from "chai";
import { time } from "@nomicfoundation/hardhat-network-helpers";
describe("BoostController - Inaccurate User Boost Update", function () {
let boostController, veToken, owner, user, dummyGauge;
beforeEach(async function () {
[owner, user] = await ethers.getSigners();
});
it("should update boost inaccurately using a fixed base amount", async function () {
// First update with the initial veToken balance of 100 units
await boostController.connect(owner).updateUserBoost(user.address, dummyGauge.address);
const userBoostData = await boostController.getUserBoost(user.address, dummyGauge.address);
});
});
Then update the boost multiplier (and/or the boost calculation logic) to use linear interpolation:
Modify the pool update logic so that instead of directly assigning newBoost to poolBoost.workingSupply, the contract aggregates boost contributions from all users. This change may require maintaining a running total and updating it when any user’s boost changes.
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.