Summary
GaugeController allows Gauge's admin to turn on gauges even when GaugeController is paused and gauge was emergency shutdown bypassing emergency pause / shutdown measures
Vulnerability Details
This is due to GaugeController::toggleGaugeStatus lacks of whenNotPaused modifier
@> function toggleGaugeStatus(address gauge) external onlyGaugeAdmin {
if (!isGauge(gauge)) revert GaugeNotFound();
gauges[gauge].isActive = !gauges[gauge].isActive;
emit GaugeStatusUpdated(gauge, gauges[gauge].isActive);
}
so even if GaugeController is paused and enters in emergency mode by an EMERGENCY_ADMIN:
function setEmergencyPause(bool paused) external {
if (!hasRole(EMERGENCY_ADMIN, msg.sender)) revert UnauthorizedCaller();
if (paused) {
@> _pause();
Gauge can still turn on by a GAUGE_ADMIN leaving emergency pause pointless
The following PoC shows the described scenario:
Emergency admin pause gaugeController using setEmergencyPause
Emergency admin shutdowns gauge
GaugeAdmin turn on gauge even gaugeController is paused and gauge has been emergency turned off
Save this test in test/unit/core/governance/gauges/GaugeController.test.js under "Emergency Controls" section:
it("it allows to turn on gauge even if emergencyshutdown and gaugecontroller is paused ", async () => {
console.log("[i] Pausing gaugeController");
await gaugeController.connect(emergencyAdmin).setEmergencyPause(true);
expect(await gaugeController.paused()).to.be.true;
console.log("[i] emergencyShutdown gauge");
await gaugeController.connect(emergencyAdmin).emergencyShutdown(await rwaGauge.getAddress());
console.log("[i] Is gaugeController paused?",
await gaugeController.paused()
);
console.log("[i] gaugeAdmin turns on gauge even when gaugeController is paused and gauge was emergencyShutdown");
await gaugeController.connect(gaugeAdmin).toggleGaugeStatus(await rwaGauge.getAddress());
});
Execute test and observe gauge can be turned on bypassing emergency mode
reset; npx hardhat test test/unit/core/governance/gauges/GaugeController.test.js --network localhost
Impact
Lack of whenNotPaused modifier allows bypassing GaugeController emergency mode
Tools Used
Manual Review
Recommendations
Implement whenNotPaused modifier on GaugeController::toggleGaugeStatus
function toggleGaugeStatus(address gauge) external onlyGaugeAdmin whenNotPaused {
if (!isGauge(gauge)) revert GaugeNotFound();
gauges[gauge].isActive = !gauges[gauge].isActive;
emit GaugeStatusUpdated(gauge, gauges[gauge].isActive);
}