QuantAMM

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

Missing Input Size Validation the _setRule function takes several array inputs but does not verify whether these arrays have consistent sizes.

Summary

The _setRule function accepts several array inputs:

  1. _initialWeights

  2. _ruleIntermediateValues

  3. _initialMovingAverages

  4. _poolSettings.lambda

However, the function lacks comprehensive checks to ensure that these arrays:

  • Have consistent lengths where required

  • Meet minimum or expected size constraints.

Vulnerability Details

  • Mismatched array lengths could trigger out-of-bounds array access, leading to transaction reverts.

  • If the function does not revert but initializes incorrectly, the pool could be left in a misconfigured state, affecting its functionality and security.

  • The contract could end up in a misconfigured state, potentially causing weight calculations or other pool logic to fail.

  • Missing validation can result in silent misconfigurations that cause downstream issues in pool operations or weight calculations.

function _setRule(
int256[] memory _initialWeights,
int256[] memory _ruleIntermediateValues,
int256[] memory _initialMovingAverages,
IQuantAMMWeightedPool.PoolSettings memory _poolSettings
) internal {
require(address(_poolSettings.rule) != address(0), "Invalid rule");
for (uint i; i < _poolSettings.lambda.length; ++i) {
int256 currentLambda = int256(uint256(_poolSettings.lambda[i]));
require(currentLambda > PRBMathSD59x18.fromInt(0) && currentLambda < PRBMathSD59x18.fromInt(1), "INVLAM"); //Invalid lambda value
}
require(
_poolSettings.lambda.length == 1 || _poolSettings.lambda.length == _initialWeights.length,
"Either scalar or vector"
);
int256 currentEpsilonMax = int256(uint256(_poolSettings.epsilonMax));
require(
currentEpsilonMax > PRBMathSD59x18.fromInt(0) && currentEpsilonMax <= PRBMathSD59x18.fromInt(1),
"INV_EPMX"
); //Invalid epsilonMax value
//applied both as a max (1 - x) and a min, so it cant be more than 0.49 or less than 0.01
//all pool logic assumes that absolute guard rail is already stored as an 18dp int256
require(
int256(uint256(_poolSettings.absoluteWeightGuardRail)) <
PRBMathSD59x18.fromInt(1) / int256(uint256((_initialWeights.length))) &&
int256(uint256(_poolSettings.absoluteWeightGuardRail)) >= 0.01e18,
"INV_ABSWGT"
); //Invalid absoluteWeightGuardRail value
require(_poolSettings.oracles.length > 0, "NOPROVORC"); //No oracle indices provided
require(_poolSettings.rule.validParameters(_poolSettings.ruleParameters), "INVRLEPRM"); //Invalid rule parameters
//0 is hodl, 1 is trade whole pool which invariant doesnt let you do anyway
require(_poolSettings.maxTradeSizeRatio > 0 && _poolSettings.maxTradeSizeRatio <= 0.3e18, "INVMAXTRADE"); //Invalid max trade size
lambda = _poolSettings.lambda;
epsilonMax = _poolSettings.epsilonMax;
absoluteWeightGuardRail = _poolSettings.absoluteWeightGuardRail;
maxTradeSizeRatio = _poolSettings.maxTradeSizeRatio;
ruleParameters = _poolSettings.ruleParameters;
_poolSettings.rule.initialisePoolRuleIntermediateValues(
address(this),
_initialMovingAverages,
_ruleIntermediateValues,
_initialWeights.length
);
updateWeightRunner.setRuleForPool(_poolSettings);
}

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/QuantAMMWeightedPool.sol#L756-L809

Tools Used

  • Manual Code Review

  • Formal Verification Tools

Recommendations

  • Add validations for all array inputs to ensure they are non-empty and consistent in length where required:

require(_initialWeights.length > 0, "Empty _initialWeights");
require(_ruleIntermediateValues.length == _initialWeights.length, "Mismatched _ruleIntermediateValues");
require(_initialMovingAverages.length == _initialWeights.length, "Mismatched _initialMovingAverages");

Set upper bounds for the lengths of input arrays to prevent excessive gas consumption:

require(_initialWeights.length <= MAX_POOL_SIZE, "Input exceeds maximum size");

Ensure all array inputs align with the pool's logic. For example:

  • _poolSettings.lambda length must match _initialWeights in vector scenarios.

  • Other inputs should have consistent sizes based on their usage in external calls.

Updates

Lead Judging Commences

n0kto Lead Judge 11 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.

Give us feedback!