The QuantAMM protocol implements dynamic weight adjustment through various update rules (MomentumUpdateRule
, AntimomentumUpdateRule
, etc.) that inherit from the base QuantAMMGradientBasedRule
contract. These rules adjust pool weights based on price movements and market signals to optimize pool performance.
The core weight adjustment mechanism relies on a normalization process to maintain proper weight balance across assets. This process is implemented in each rule's _getWeights()
function, which calculates new weights using price gradients, moving averages, and rule-specific parameters.
An issue exists in the weight normalization implementation where division operations are performed before multiplication in fixed-point arithmetic calculations. In MomentumUpdateRule._getWeights()
:
MomentumUpdateRule.sol#L97-L105
This pattern appears across all update rules, creating systemic precision loss that compounds with each weight update cycle. In fixed-point arithmetic, performing division before multiplication can lose up to 18 decimal places of precision per operation. The lost precision accumulates through both the normalization calculations and subsequent weight adjustments.
High severity as precision loss compounds over time, leading to pool weight imbalances that can cause significant value loss for LPs through incorrect price calculations and arbitrage opportunities. The systemic nature affects all gradient-based rules and becomes more severe with frequent updates and multiple tokens.
Consider a two-token pool scenario:
Initial setup:
Pool weights: [5e18, 5e18] (50-50 split)
Price gradients: [1e17, 2e17]
Kappa parameter: 1e17
First update cycle:
normalizationFactor = (1e17 + 2e17) / 2 // Truncates to 1e17
weight[0] = 5e18 + 1e17 * (1e17 - 1e17) = 5e18
weight[1] = 5e18 + 1e17 * (2e17 - 1e17) = 5.1e18
// Total weights: 101%
Subsequent updates compound the error:
Cycle 2: [5e18, 5.21e18] (102.1%)
Cycle 3: [5e18, 5.33e18] (103.3%)
Each cycle increases weight imbalance
Impact materializes:
Pool invariant broken
Incorrect price calculations
Arbitrage opportunities emerge
LP value erosion accelerates
Manual Review
Restructure the weight normalization calculation to perform all multiplications before any division operations. This can be achieved by first accumulating the total weighted adjustments through multiplication, then performing a single division at the end for normalization, which will minimize precision loss and prevent the compounding of rounding errors across multiple update cycles.
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.
According the sponsor and my understanding, sum of weights does not have to be exactly 1 to work fine. So no real impact here. Please provide a PoC showing a realistic impact if you disagree. This PoC cannot contains negative weights because they will be guarded per clampWeights.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.