Core Contracts

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

veRAAC's lock may be blocked

Summary

veRAAC's lock may be blocked

Vulnerability Details

When users lock RAAC in the veRAAC contract, we will trigger _boostState.updateBoostPeriod(). In function updateBoostPeriod(), we will create one 7-days duration period when we lock RAAC at the first time. In the next 7 days, we will update the total duration in function updateValue().

When we create this period, the period's totalDuration is 7 days. When we lock again in the next 7 days, we will add the delta time into the total duration. So the period's total duration will be larger than 7 days.

When current timestamp is larger than periodStart + state.boostWindow, we expect to start one new period. But the problem is that there is one check in createPeriod(): startTime < self.startTime + self.totalDuration. This check will fail, because current total Duration is larger than 7 days. This will cause that veRAAC's lock will be reverted.

For example:

  1. Alice locks some RAAC in timestamp X. We create one period, period.startTime = X, period.totalDuration = 7 days.

  2. Bob locks some RAAC in timestamp X + 7 days - 2, we will update value, the period.totalDuration will increase to around 14 days.

  3. Cathy wants to lock some RAAC in timestamp X + 7 days + 2, we need to create one new period, but timestamp X + 7 days + 2 < timestamp X + 14 days. Cathy's lock will be reverted.

function updateBoostPeriod(
BoostState storage state
) internal {
if (state.boostWindow == 0) revert InvalidBoostWindow();
if (state.maxBoost < state.minBoost) revert InvalidBoostBounds();
uint256 currentTime = block.timestamp;
uint256 periodStart = state.boostPeriod.startTime;
// If no period exists, create initial period starting from current block
if(periodStart > 0) {
if (currentTime >= periodStart + state.boostWindow) {
TimeWeightedAverage.createPeriod(
state.boostPeriod,
currentTime,
state.boostWindow,
state.votingPower,
state.maxBoost
);
return;
}
state.boostPeriod.updateValue(state.votingPower, currentTime);
return;
}
TimeWeightedAverage.createPeriod(
state.boostPeriod,
currentTime, // block.timestamp
state.boostWindow, // duration. 7 days.
state.votingPower,
state.maxBoost
);
}
function updateValue(
Period storage self,
uint256 newValue,
uint256 timestamp
) internal {
// we should update value in the period.
if (timestamp < self.startTime || timestamp > self.endTime) {
revert InvalidTime();
}
unchecked {
uint256 duration = timestamp - self.lastUpdateTime;
if (duration > 0) {
uint256 timeWeightedValue = self.value * duration;
if (timeWeightedValue / duration != self.value) revert ValueOverflow();
self.weightedSum += timeWeightedValue;
self.totalDuration += duration; // 7 days + delta.
}
}
self.value = newValue;
self.lastUpdateTime = timestamp;
}

Impact

veRAAC's lock will not work for 7 days.

Tools Used

Manual

Recommendations

Updates

Lead Judging Commences

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

veRAACToken lock can be blocked for extended periods due to TimeWeightedAverage period duration inconsistency

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

veRAACToken lock can be blocked for extended periods due to TimeWeightedAverage period duration inconsistency

Appeal created

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

veRAACToken can be DOSed when totalDuration exceeds boostWindow in TimeWeightedAverage, preventing new users from locking tokens until extended duration elapses

veRAACToken lock can be blocked for extended periods due to TimeWeightedAverage period duration inconsistency

Support

FAQs

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