QuantAMM

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

No Mechanism to Remove or Update Pool Rules After Initial Setting

Description

The UpdateWeightRunner contract allows pools to set their rules through the setRuleForPool function, but provides no mechanism to update or remove these rules once set. This is implemented through a one-time setting mechanism:

function setRuleForPool(IQuantAMMWeightedPool.PoolSettings memory _poolSettings) external {
require(address(rules[msg.sender]) == address(0), "Rule already set");
require(_poolSettings.oracles.length > 0, "Empty oracles array");
require(poolOracles[msg.sender].length == 0, "pool rule already set");
// ... setting logic
}

While this immutability might be intentional for gas optimization and security through simplicity (as noted in the architecture documentation), the complete lack of any emergency or migration mechanism creates significant risks.

The rules are stored permanently in these mappings:

mapping(address => IUpdateRule) private rules;
mapping(address => PoolRuleSettings) private poolRuleSettings;

Impact

The inability to update or remove rules can lead to several critical issues:

  1. Permanent Lock-in to Buggy Rules

    • If a mathematical error is discovered in a rule's implementation

    • If a rule becomes vulnerable to manipulation under certain market conditions

    • If regulatory changes require modifications to rule behavior

  2. No Recovery from Suboptimal States

    • Pools stuck with underperforming rules cannot be optimized

    • No way to adapt to changing market conditions or new trading patterns

    • Cannot implement improvements or optimizations to rule calculations

  3. Financial Risks

    • Users could suffer losses from continued use of buggy rules

    • Protocol could face reputational damage from inability to fix known issues

    • Potential for permanent loss of funds if a critical vulnerability is discovered

Mitigation

Multiple approaches could be implemented to address this issue while maintaining the benefits of the current design:

Rule Migration System

This system allows for a controlled transition from one rule to another. Here's how it works:

function migratePoolRule(
address poolAddress,
IUpdateRule newRule,
PoolRuleSettings memory newSettings
) external {
require(msg.sender == quantammAdmin, "ONLYADMIN");
require(address(rules[poolAddress]) != address(0), "No rule set");
// Optional: Timelock or governance approval
rules[poolAddress] = newRule;
poolRuleSettings[poolAddress] = newSettings;
emit RuleMigrated(poolAddress, address(newRule));
}

Emergency Rule Suspension

This is a safety mechanism to quickly stop a problematic rule:

function emergencySuspendRule(address poolAddress) external {
require(msg.sender == quantammAdmin, "ONLYADMIN");
require(address(rules[poolAddress]) != address(0), "No rule set");
// Store the suspended state
isSuspended[poolAddress] = true;
emit RuleSuspended(poolAddress);
}
Updates

Lead Judging Commences

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

Informational or Gas / Admin is trusted / Pool creation is trusted / User mistake / Suppositions

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

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