Core Contracts

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

Incorrect logic for gauge weight update.

Summary

Contract - GaugeController.sol

In current implementation user can vote on particular gauge, and can increase it's weight, via calling vote() function.

function vote(address gauge, uint256 weight) external override whenNotPaused {
if (!isGauge(gauge)) revert GaugeNotFound();
if (weight > WEIGHT_PRECISION) revert InvalidWeight();
uint256 votingPower = veRAACToken.balanceOf(msg.sender);
if (votingPower == 0) revert NoVotingPower();
uint256 oldWeight = userGaugeVotes[msg.sender][gauge];
userGaugeVotes[msg.sender][gauge] = weight;
_updateGaugeWeight(gauge, oldWeight, weight, votingPower);
emit WeightUpdated(gauge, oldWeight, weight);
}

_updateGaugeWeight()

function _updateGaugeWeight(
address gauge,
uint256 oldWeight,
uint256 newWeight,
uint256 votingPower
) internal {
Gauge storage g = gauges[gauge];
uint256 oldGaugeWeight = g.weight;
@-> uint256 newGaugeWeight = oldGaugeWeight - (oldWeight * votingPower / WEIGHT_PRECISION)
+ (newWeight * votingPower / WEIGHT_PRECISION);
g.weight = newGaugeWeight;
g.lastUpdateTime = block.timestamp;
}

Incorrect logic part -

(oldWeight * votingPower / WEIGHT_PRECISION)

currently, multiplication of oldWeight of user and current veRACC holding of user is performed, but it's may be possible that veRAAC holding user earlier (during oldWeight time), is less compared to current holding; or veRAAC holding of user earlier (during oldWeight time) is higher than current holder.

So the point is that, the multiplication should be done between user's old weight and user's old voting power/ veRAAC holding; instead of user's old weight and user's current voting power.

Vulnerability Details

Same as above

Impact

Incorrect updating of gauge weight or g.weight, with incorrect value.

Tools Used

Manual

Recommendations

Create new state variable struct for user, to track the voting status. something like -

struct UserVoteStatus{
uint256 last_User_Weight;
uint256 last_RAAC_holding;
uint256 last_timestamp;
}
// userAddress -> block.timestamp -> user vote status.
mapping(address => mapping(uint256 => UserVoteStatus))

Implement something like this in vote() function instead of -

(oldWeight * votingPower / WEIGHT_PRECISION)
Updates

Lead Judging Commences

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

GaugeController::_updateGaugeWeight uses current voting power for both old and new vote calculations, causing underflows when voting power increases and incorrect gauge weights

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

GaugeController::_updateGaugeWeight uses current voting power for both old and new vote calculations, causing underflows when voting power increases and incorrect gauge weights

Support

FAQs

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