Core Contracts

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

`getRewards` update the lastClaim time even in case user claim 0 amount

Summary

The getRewards function updates the user's lastClaimTime even when they have zero rewards to claim.

Vulnerability Details

The protocol allows users to claim rewards after MIN_CLAIM_INTERVAL. However, the lastClaimTime of the user is updated even if the reward amount is 0, as shown in the code below.

/contracts/core/governance/gauges/BaseGauge.sol:327
327: function getReward() external virtual nonReentrant whenNotPaused updateReward(msg.sender) {
328: if (block.timestamp - lastClaimTime[msg.sender] < MIN_CLAIM_INTERVAL) {
329: revert ClaimTooFrequent();
330: }
331:
332: lastClaimTime[msg.sender] = block.timestamp;
333: UserState storage state = userStates[msg.sender];
334: uint256 reward = state.rewards;
335:
336: if (reward > 0) {
337: state.rewards = 0;
338:
339: uint256 balance = rewardToken.balanceOf(address(this));
340: if (reward > balance) {
341: revert InsufficientBalance();
342: }
343:
344: rewardToken.safeTransfer(msg.sender, reward);
345: emit RewardPaid(msg.sender, reward);
346: }
347: }

This could create a problem in edge cases where the MIN_CLAIM_INTERVAL has passed, but the user's reward amount is 0. If the user calls the getRewards function at this point, they will be unable to call it again until the next MIN_CLAIM_INTERVAL, even if they accrue rewards in the meantime.

Impact

If a user's last call to getRewards returned 0 rewards, they will be unable to claim rewards again until the MIN_CLAIM_INTERVAL has passed, even if they have accrued rewards in the meantime.

Tools Used

Manual Review

Recommendations

The best approach could be to only update the lastClaimTime when the user accrued some reward amount :

diff --git a/contracts/core/governance/gauges/BaseGauge.sol b/contracts/core/governance/gauges/BaseGauge.sol
index 479c90b..844e4d1 100644
--- a/contracts/core/governance/gauges/BaseGauge.sol
+++ b/contracts/core/governance/gauges/BaseGauge.sol
@@ -329,12 +329,12 @@ abstract contract BaseGauge is IGauge, ReentrancyGuard, AccessControl, Pausable
revert ClaimTooFrequent();
}
- lastClaimTime[msg.sender] = block.timestamp;
UserState storage state = userStates[msg.sender];
uint256 reward = state.rewards;
if (reward > 0) {
state.rewards = 0;
+ lastClaimTime[msg.sender] = block.timestamp;
uint256 balance = rewardToken.balanceOf(address(this));
if (reward > balance) {
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!