Core Contracts

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

BaseGauge::stake don't check for paused status to perform operations, allowing users to put their funds at risk during emergency times.

Summary

BaseGauge implement the setEmergencyPausedfunctionality to stop critical functionalities during adverse times. However, the functionality ignores critical functions such as stake and withdrawal.

Vulnerability Details

The BaseGauge::stake function doesn't have the whenNotPausedallowing users to deposit money on the protocol even during an emergency state.

Impact

Users can put their money into the contract while measures to mitigate an exploit are discussed. This can lead to lost funds.

Tools Used

Code review

///SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {Test, console} from "forge-std/Test.sol";
//Collectors Contracts
import { FeeCollector } from "src/core/collectors/FeeCollector.sol";
import { Treasury } from "src/core/collectors/Treasury.sol";
//Governance -> boost
import { BoostController } from "src/core/governance/boost/BoostController.sol";
//Governance -> Gauges
import { GaugeController } from "src/core/governance/gauges/GaugeController.sol";
import { RAACGauge } from "src/core/governance/gauges/RAACGauge.sol";
import { RWAGauge } from "src/core/governance/gauges/RWAGauge.sol";
//Governance -> Proposals
import { Governance } from "src/core/governance/proposals/Governance.sol";
import { TimelockController } from "src/core/governance/proposals/TimelockController.sol";
//Minter -> RAACMinter
import { RAACMinter } from "src/core/minters/RAACMinter/RAACMinter.sol";
//Minter -> RAACReleaseOrchestrator
import { RAACReleaseOrchestrator } from "src/core/minters/RAACReleaseOrchestrator/RAACReleaseOrchestrator.sol";
//Oracles
import { RAACHousePriceOracle } from "src/core/oracles/RAACHousePriceOracle.sol";
import { RAACPrimeRateOracle } from "src/core/oracles/RAACPrimeRateOracle.sol";
//Pools - LendingPool
import { LendingPool } from "src/core/pools/LendingPool/LendingPool.sol";
//Pools - StabilityPool
import { MarketCreator } from "src/core/pools/StabilityPool/MarketCreator.sol";
import { NFTLiquidator } from "src/core/pools/StabilityPool/NFTLiquidator.sol";
import { StabilityPool } from "src/core/pools/StabilityPool/StabilityPool.sol";
//Primitives
import { RAACHousePrices } from "src/core/primitives/RAACHousePrices.sol";
//Tokens
import { DebtToken } from "src/core/tokens/DebtToken.sol";
import { DEToken } from "src/core/tokens/DEToken.sol";
import { IndexToken } from "src/core/tokens/IndexToken.sol";
import { LPToken } from "src/core/tokens/LPToken.sol";
import { RAACNFT } from "src/core/tokens/RAACNFT.sol";
import { RAACToken } from "src/core/tokens/RAACToken.sol";
import { RToken } from "src/core/tokens/RToken.sol";
import { veRAACToken } from "src/core/tokens/veRAACToken.sol";
//Zeno
import { Auction } from "src/zeno/Auction.sol";
import { ZENO } from "src/zeno/ZENO.sol";
//Mocks
import { MockAsset } from "test/Mocks/MockAsset.sol";
import { MockUSDC } from "test/Mocks/MockUSDC.sol";
contract BaseTests is Test {
///Contracts
FeeCollector public s_collector; //deployed -> SCOPE
Treasury public s_treasury; //deployed -> SCOPE
BoostController public s_boostController; //deployed -> SCOPE
GaugeController public s_gaugeController; //deployed -> SCOPE
RAACGauge public s_raacGauge; //deployed -> SCOPE
RWAGauge public s_rwaGauge; //deployed -> SCOPE
Governance public s_governance; //deployed -> SCOPE
TimelockController public s_timeLockController; //deployed -> SCOPE
RAACMinter public s_raacMinter; //deployed -> SCOPE
RAACReleaseOrchestrator public s_raacOrchestrator; //deployed -> SCOPE
RAACHousePriceOracle public s_raacPriceOracle; //deployed -> SCOPE
RAACPrimeRateOracle public s_raacPrimeRateOracle;// -> SCOPE ------------> NOT DEPLOYED YET
LendingPool public s_lendingPool; //deployed -> SCOPE
MarketCreator public s_marketCreator;
NFTLiquidator public s_nftLiquidator;
StabilityPool public s_stabilityPool; //deployed -> SCOPE
RAACHousePrices public s_raacHousePrices; //deployed -> SCOPE
DebtToken public s_debtToken; //deployed -> SCOPE
DEToken public s_deToken; //deployed -> SCOPE
IndexToken public s_indexToken;
LPToken public s_lpToken; //deployed
RAACNFT public s_raacNFT; //deployed -> SCOPE
RAACToken public s_raacToken; //deployed -> SCOPE
RToken public s_rToken; //deployed -> SCOPE
veRAACToken public s_veToken; //deployed -> SCOPE
Auction public s_auction; //deployed -> SCOPE
ZENO public s_zeno; //deployed -> SCOPE
//Governance Actors
address s_proposer1 = makeAddr("proposer1");
address s_proposer2 = makeAddr("proposer2");
address s_proposer3 = makeAddr("proposer3");
address s_proposer4 = makeAddr("proposer4");
address s_executor1 = makeAddr("executor1");
address s_executor2 = makeAddr("executor2");
address s_executor3 = makeAddr("executor3");
address s_executor4 = makeAddr("executor4");
//Others
address public s_repairFund = makeAddr("repairFund");
address public s_businessAddress = makeAddr("businessAddress");
MockAsset public s_assetToken; //deployed
MockUSDC public s_usdc; //deployed
//Users
address public s_admin = makeAddr("admin");
address public s_user01 = makeAddr("s_user01");
//Token Amounts
uint256 constant public INITIAL_PRICE = 100*10**6;
uint256 constant public RESERVE_PRICE = 50*10**18;
function setUp() public virtual {
vm.warp(1739824870);
vm.startPrank(s_admin);
// Deploy 1
s_treasury = new Treasury(s_admin);
// Deploy 2
s_raacToken = new RAACToken(
s_admin,
0, //it will default to 1%
0 //it will default to 0.5%
);
// Deploy 3
s_veToken = new veRAACToken(address(s_raacToken));
// Deploy 4
s_collector = new FeeCollector(
address(s_raacToken),
address(s_veToken),
address(s_treasury),
s_repairFund,
s_admin
);
// Deploy 5
s_boostController = new BoostController(address(s_veToken));
// Deploy 6
s_gaugeController = new GaugeController(address(s_veToken));
// Deploy 7
s_assetToken = new MockAsset("Asset Token", "ATN");
s_usdc = new MockUSDC("Mock USDC", "USDC");
// Deploy 8
s_rToken = new RToken(
"Reward Token",
"rToken",
s_admin,
address(s_assetToken)
);
//Deploy 9
s_lpToken = new LPToken(
"LP Token",
"LPT",
s_admin
);
//Deploy 10
s_raacGauge = new RAACGauge(
address(s_rToken),
address(s_lpToken),
address(s_gaugeController)
);
//Deploy 11
s_rwaGauge = new RWAGauge(
address(s_rToken),
address(s_lpToken),
address(s_gaugeController)
);
//Deploy 12
s_debtToken = new DebtToken(
"Debt Token",
"DBT",
s_admin
);
//Deploy 13
s_raacHousePrices = new RAACHousePrices(s_admin);
//Deploy 14
s_raacPriceOracle = new RAACHousePriceOracle(
address(0),
0x66756e2d657468657265756d2d6d61696e6e65742d3100000000000000000000,
address(s_raacHousePrices)
);
//Deploy 15
s_raacNFT = new RAACNFT(
address(s_assetToken),
address(s_raacHousePrices),
s_admin
);
//Deploy 16
s_stabilityPool = new StabilityPool(
s_admin
);
//Deploy 17
s_lendingPool = new LendingPool(
address(s_assetToken),
address(s_rToken),
address(s_debtToken),
address(s_raacNFT),
address(s_raacPriceOracle),
1 //TODO
);
//Deploy 18
s_raacMinter = new RAACMinter(
address(s_raacToken),
address(s_stabilityPool),
address(s_lendingPool),
s_admin
);
//Deploy 19
s_timeLockController = new TimelockController(
5 days,
addProposers(),
addExecutors(),
s_admin
);
//Deploy 20
s_governance = new Governance(
address(s_veToken),
address(s_timeLockController)
);
//Deploy 21
s_raacOrchestrator = new RAACReleaseOrchestrator(address(s_raacToken));
//Deploy 22
s_deToken = new DEToken(
"DE Token",
"DET",
s_admin,
address(s_rToken)
);
//Deploy 23
s_zeno = new ZENO(
address(s_usdc),
block.timestamp + 1 days,
"Zeno Token",
"ZENO",
s_admin
);
//Deploy 24
s_auction = new Auction(
address(s_zeno),
address(s_usdc),
s_businessAddress,
block.timestamp + 1 days,
block.timestamp + 4 days,
INITIAL_PRICE,
RESERVE_PRICE,
RESERVE_PRICE, //totalAllocated
s_admin
);
vm.stopPrank();
}
function addProposers() public returns(address[] memory){
address[] memory proposers = new address[](4);
proposers[0] = (s_proposer1);
proposers[1] = (s_proposer2);
proposers[2] = (s_proposer3);
proposers[3] = (s_proposer4);
return proposers;
}
function addExecutors() public returns(address[] memory){
address[] memory executors = new address[](4);
executors[0] = (s_executor1);
executors[1] = (s_executor2);
executors[2] = (s_executor3);
executors[3] = (s_executor4);
return executors;
}
}
function test_deactivatedGaugesStillCanReceiveStakes() public {
uint256 stakingAmount = 10*10**18;
//mint to the user to perform the deposit
vm.startPrank(s_admin);
s_lpToken.mint(s_user01, stakingAmount);
//pause the contract so critical functions are not performed during pause state
s_raacGauge.setEmergencyPaused(true);
vm.stopPrank();
vm.startPrank(s_user01);
s_lpToken.approve(address(s_raacGauge), stakingAmount);
s_raacGauge.stake(stakingAmount);
s_raacGauge.withdraw(stakingAmount);
vm.stopPrank();
}

Recommendations

Although withdraws should not be blocked, the stake functionality should be blocked during emergency state.

Add the whenNotPaused to the BaseGauge::stakefunction.

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!