Core Contracts

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

Missing whenNotPaused modifier on staking functions allows rewards to accrue during emergency pause

Summary

The stake() and withdraw() functions in BaseGauge lack the whenNotPaused modifier, allowing users to continue staking and accruing rewards even when the contract is emergency paused.

Vulnerability Details

The BaseGauge contract implements Pausable functionality to allow emergency halting of operations. However, the critical staking functions stake() and withdraw() are missing the whenNotPaused modifier:

function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
if (amount == 0) revert InvalidAmount();
_totalSupply += amount;
_balances[msg.sender] += amount;
stakingToken.safeTransferFrom(msg.sender, address(this), amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount) external nonReentrant updateReward(msg.sender) {
if (amount == 0) revert InvalidAmount();
if (_balances[msg.sender] < amount) revert InsufficientBalance();
_totalSupply -= amount;
_balances[msg.sender] -= amount;
stakingToken.safeTransfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}

This oversight means that even when the contract is paused via setEmergencyPaused(true), users can continue to:

  1. Stake new tokens

  2. Withdraw staked tokens

  3. Accrue rewards through the updateReward modifier

This defeats the purpose of the emergency pause mechanism which is intended to halt all contract operations during critical situations.

Proof of Concept

  1. Admin calls setEmergencyPaused(true) due to discovered vulnerability

  2. Despite pause, users can still call stake() to deposit tokens

  3. The updateReward modifier continues updating reward state

  4. Users accrue rewards during the emergency pause period

  5. Once unpaused, users can claim accumulated rewards via getReward()

Impact

  • Emergency pause mechanism is partially ineffective

  • Users can continue to interact with core staking functionality during critical situations

  • Rewards continue to accrue when they should be frozen

  • Potential financial loss if rewards need to be halted immediately

Recommendations

Add whenNotPaused modifier

- function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
+ function stake(uint256 amount) external nonReentrant whenNotPaused updateReward(msg.sender) {
- function withdraw(uint256 amount) external nonReentrant updateReward(msg.sender) {
+ function withdraw(uint256 amount) external nonReentrant whenNotPaused updateReward(msg.sender) {
Updates

Lead Judging Commences

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

BaseGauge::withdraw, stake, and checkpoint functions lack whenNotPaused modifier, allowing critical state changes even during emergency pause

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

BaseGauge::withdraw, stake, and checkpoint functions lack whenNotPaused modifier, allowing critical state changes even during emergency pause

Support

FAQs

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

Give us feedback!