QuantAMM

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

Weight storage capacity mismatch in `QuantAMMWeightedPool`

Summary

The QuantAMMWeightedPool contract has a severe architectural restriction. While it can initialize pools with an unlimited number of tokens, its hard-coded weight storage structure limits it to only 8 tokens. This guarantees dysfunction and potential value loss for all tokens beyond the eighth place.

Vulnerability Details

The contract’s weight storage mechanism is limited to handling 8 tokens:

int256 internal _normalizedFirstFourWeights; // Tokens 0-3
int256 internal _normalizedSecondFourWeights; // Tokens 4-7

However, the contract permits initialization with an arbitrary number of tokens and initialweights:

function initialize(...) public initializer {
require(_poolSettings.assets.length > 0 && _poolSettings.assets.length == _initialWeights.length, "INVASSWEIG");
assets = _poolSettings.assets; // Can accept unlimited tokens\
}

When the _getNormalizedWeights() function is called, it processes weights for only the first 8 tokens and silently fails to fetch weights for any additional tokens, as shown below:

if (totalTokens > 7) {
normalizedWeights[7] = calculateBlockNormalisedWeight(
secondFourWeights[3],
secondFourWeights[moreThan4Tokens + 3],
timeSinceLastUpdate
);
} else {
return normalizedWeights;
}

Real-World Example: Pool with 12 Tokens

Scenario:

  • A pool is initialized with 12 tokens and weights.

  • Weights for tokens 1–8 are stored in _normalizedFirstFourWeights and _normalizedSecondFourWeights.

  • Tokens 9–12 do not have corresponding storage for weights.

Execution:

  • _getNormalizedWeights() calculates and returns weights for tokens 1–8.

  • Tokens 9–12 are not returned as they are not handled by the function

Resulting Normalized Weights Array:
[5001000, 20002000, 45003000, 80004000, 125005000, 180006000, 245007000, 320008000]

Impact:

  • Tokens 9–12 weights are never returned and become untradeable.

Impact

  • The pool’s mechanics fail to handle weights for tokens beyond the 8th position, even when the initializer makes it possible to initialize more than 8 weights and 8 tokens, rendering them unusable .

Tools Used

  • Manual code review

  • Static analysis

Recommendations

  1. Strict Validation:
    Enforce a hard cap on the number of tokens during initialization to prevent unsupported configurations.

    require(_poolSettings.assets.length <= 8, "Pool cannot exceed 8 tokens");
  2. Redesign Storage Structure:
    If more tokens are needed, adopt a flexible weight storage mechanism to accommodate additional tokens.

    mapping(uint256 => int256) internal normalizedWeights;

Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
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.