Core Contracts

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

Users will not take the rewards as they expected because the rewards are in bias scores in BaseGauge.sol

Summary

Users will not take the rewards as they expected because the rewards are in bias scores in BaseGauge.sol.

Vulnerability Details

When users wants to take their rewards they use the getReward() which updates the user rewards and then trasfered them. But when they are updated it uses the function earned() and returns the rewards that the user accumulated. But the earned function doesnt return the amount of rewards as it should, instead it return bias score.

function getReward() external virtual nonReentrant whenNotPaused updateReward(msg.sender) { // here
if (block.timestamp - lastClaimTime[msg.sender] < MIN_CLAIM_INTERVAL) {
revert ClaimTooFrequent();
}
lastClaimTime[msg.sender] = block.timestamp;
UserState storage state = userStates[msg.sender];
uint256 reward = state.rewards;
if (reward > 0) {
state.rewards = 0;
uint256 balance = rewardToken.balanceOf(address(this));
if (reward > balance) {
revert InsufficientBalance();
}
rewardToken.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function _updateReward(address account) internal {
rewardPerTokenStored = getRewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
UserState storage state = userStates[account];
state.rewards = earned(account); // here
state.rewardPerTokenPaid = rewardPerTokenStored;
state.lastUpdateTime = block.timestamp;
emit RewardUpdated(account, state.rewards);
}
}
/**
* @notice Calculates earned rewards for account
* @param account Address to calculate earnings for
* @return Amount of rewards earned
*/
function earned(address account) public view returns (uint256) {
return ((getUserWeight(account) * (getRewardPerToken() - userStates[account].rewardPerTokenPaid)) / 1e18) //@audit-info the calc is (1e4 * (1e18 - 1e18)) / 1e18 = 1e4
+ userStates[account].rewards;
}

getUserWeight return 4 decimals, getRewardPerToken return 18 decimals and userStates[account].rewardPerTokenPaid returns 18 decimals, which means that the earned() will always return 4 decimals

Impact

The user will not take the all of his rewards which are due to him.

Tools Used

Recommendations

Return the amount of rewards as it is stayted in the comments

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

BaseGauge reward calculations divide by 1e18 despite using 1e4 precision weights, causing all user weights to round down to zero and preventing reward distribution

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.