Summary
calculateBoost function in BoostController contract is defined as follows:
function calculateBoost(address user, address pool, uint256 amount)
external
view
override
returns (uint256 boostBasisPoints, uint256 boostedAmount)
{
if (!supportedPools[pool]) revert UnsupportedPool();
(uint256 totalWeight, uint256 totalVotingPower, uint256 votingPower) = updateTotalWeight();
uint256 userVotingPower = veToken.getVotingPower(user, block.timestamp);
BoostCalculator.BoostParameters memory params = BoostCalculator.BoostParameters({
maxBoost: boostState.maxBoost,
minBoost: boostState.minBoost,
boostWindow: boostState.boostWindow,
totalWeight: totalWeight,
totalVotingPower: totalVotingPower,
votingPower: votingPower
});
return BoostCalculator.calculateTimeWeightedBoost(params, userVotingPower, totalVotingPower, amount);
}
The problem arises because BoostCalculator.calculateTimeWeightedBoost should receive user veRAACToken balance and total supply instead of the voting power:
* @notice Calculates time-weighted boost for a given amount
* @dev Applies boost multiplier to the input amount based on user's position
* @param state The boost state
* @param userBalance The user's veToken balance
* @param totalSupply The total veToken supply
* @param amount The amount to boost
* @return boostBasisPoints The calculated boost multiplier in basis points
* @return boostedAmount The calculated boosted amount
*/
function calculateTimeWeightedBoost(
BoostState storage state,
uint256 userBalance,
uint256 totalSupply,
uint256 amount
) internal view returns (uint256 boostBasisPoints, uint256 boostedAmount)
Consequences are that boost will be incorrectly computed and applied to users.
Impact
The impact of this issue is high as it leads to incorrect boost computation, which may lead to loss of rewards for users.
Tools Used
Manual review
Recommendations
Make sure to pass the correct parameters to calculateTimeWeightedBoost function.