QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: low
Invalid

Admin cannot execute breakglass functions when multiple permissions are enabled

Summary

Breakglass (emergency) functions in UpdateWeightRunner use flawed if-else logic that causes admin calls to revert when both admin and manager permissions are enabled. Despite having the permission, the admin will be unable to execute these critical emergency functions because the code first checks for manager permissions and reverts if the caller isn't the manager, never reaching the admin permission check.

Vulnerability Details

This issue occurs when both MASK_POOL_QUANTAMM_ADMIN_UPDATES and MASK_POOL_OWNER_UPDATES are enabled. It is reasonable expectation that admin can execute breakglass functions since his permission is enabled.

Let's look at InitialisePoolLastRunTime function implementation:

function InitialisePoolLastRunTime(address poolAddress, uint40 time) external {
uint256 poolRegistryEntry = approvedPoolActions[_poolAddress];
// @audit if MASK_POOL_OWNER_UPDATES (8) is enabled, this block executes first
if (poolRegistryEntry & MASK_POOL_OWNER_UPDATES > 0) {
require(
msg.sender == poolRuleSettings[_poolAddress].poolManager,
'ONLYMANAGER'
);
}
// @audit code never reaches here if first condition is true
else if (poolRegistryEntry & MASK_POOL_QUANTAMM_ADMIN_UPDATES > 0) {
require(msg.sender == quantammAdmin, 'ONLYADMIN');
}
}

If both permissions are enabled:

poolRegistryEntry = MASK_POOL_OWNER_UPDATES | MASK_POOL_QUANTAMM_ADMIN_UPDATES
= 8 | 16
= 24
First check: 24 & 8 > 0 // True
Requires msg.sender to be poolManager
Admin call will revert with "ONLYMANAGER"

The same issue is present also in setWeightsManually and setIntermediateValuesManually functions.

Impact

  • Admin cannot execute emergency function when both permissions are enabled

  • Could prevent emergency response in critical situations

  • High severity as it affects emergency functionality

Tools Used

Manual code review

Recommendations

Change the logic to use OR condition:

function InitialisePoolLastRunTime(address poolAddress, uint40 time) external {
uint256 poolRegistryEntry = approvedPoolActions[_poolAddress];
// Check if caller is either authorized admin or manager
bool isAuthorizedAdmin = (poolRegistryEntry & MASK_POOL_QUANTAMM_ADMIN_UPDATES >0) && (msg.sender == quantammAdmin);
bool isAuthorizedManager = (poolRegistryEntry & MASK_POOL_OWNER_UPDATES > 0) && (msg.sender == poolRuleSettings[_poolAddress].poolManager);
require(isAuthorizedAdmin || isAuthorizedManager, 'Not authorized');
...
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

invalid_manual_functions_cannot_be_called_by_admin_when_pool_owner_can

Design choice confirmed by the sponsor.

Support

FAQs

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