QuantAMM

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

Missing Lambda Threshold in Covariance Calculation Causes Instability and Erratic Pool Behavior

Summary

In the QuantAMMCovarianceBasedRule abstract contract, the _calculateQuantAMMCovariance function calculates the covariance matrix, a crucial component for updating pool weights. This process relies on a decay factor lambda (lambda), which balances historical data with recent observations. However, the absence of a validation check for lambda's value introduces significant vulnerabilities. Without a proper threshold, lambda can fall outside its intended range, leading to erratic calculations and destabilization of the protocol.

Vulnerability Details

QuantAMMCovarianceBasedRule::_calculateQuantAMMCovariance:

function _calculateQuantAMMCovariance(int256[] memory _newData, QuantAMMPoolParameters memory _poolParameters)
internal
returns (int256[][] memory)
{
QuantAMMCovariance memory locals;
locals.n = _poolParameters.numberOfAssets; // Dimension of square matrix
locals.nSquared = locals.n * locals.n;
int256[][] memory intermediateCovarianceState =
_quantAMMUnpack128Matrix(intermediateCovarianceStates[_poolParameters.pool], locals.n);
int256[][] memory newState = new int256[][]();
locals.u = new int256[](locals.n); // (p(t) - p̅(t - 1))
locals.v = new int256[](locals.n); // (p(t) - p̅(t))
@> // @info: missing lengths checks
// _newData array length must be >= number of assets
// _poolParameters.movingAverage array length must be >= 2 * number of assets
// Vulnerability: Out-of-bounds errors could occur if lengths are not validated.
for (uint256 i; i < locals.n;) {
locals.u[i] = _newData[i] - _poolParameters.movingAverage[i + locals.n];
locals.v[i] = _newData[i] - _poolParameters.movingAverage[i];
unchecked {
++i;
}
}
if (_poolParameters.lambda.length == 1) {
unchecked {
locals.convertedLambda = int256(_poolParameters.lambda[0]);
@> // @info: missing lambda threshold validation
// Vulnerability:
// 1. Overreaction to short-term volatility for high λ.
// 2. Excessive rigidity in pool weights for low λ.
// 3. Instability in portfolio performance.
locals.oneMinusLambda = ONE - locals.convertedLambda;
}
for (uint256 i; i < locals.n;) {
newState[i] = new int256[]();
for (uint256 j; j < locals.n;) {
locals.intermediateState = locals.convertedLambda.mul(intermediateCovarianceState[i][j])
+ locals.u[i].mul(locals.v[j]).div(TENPOWEIGHTEEN);
newState[i][j] = locals.intermediateState.mul(locals.oneMinusLambda);
intermediateCovarianceState[i][j] = locals.intermediateState;
unchecked {
++j;
}
}
unchecked {
++i;
}
}
} else {
for (uint256 i; i < locals.n;) {
unchecked {
locals.convertedLambda = int256(_poolParameters.lambda[i]);
@> // @info: missing lambda threshold validation
locals.oneMinusLambda = ONE - locals.convertedLambda;
}
newState[i] = new int256[]();
for (uint256 j; j < locals.n;) {
locals.intermediateState = locals.convertedLambda.mul(intermediateCovarianceState[i][j])
+ locals.u[i].mul(locals.v[j]).div(TENPOWEIGHTEEN);
newState[i][j] = locals.intermediateState.mul(locals.oneMinusLambda);
intermediateCovarianceState[i][j] = locals.intermediateState;
unchecked {
++j;
}
}
unchecked {
++i;
}
}
}
_quantAMMPack128Matrix(intermediateCovarianceState, intermediateCovarianceStates[_poolParameters.pool]);
return newState;
}

Vulnerabilities

  1. Unvalidated Lambda: Without validation, lambda could exceed the range, resulting in:

    • Exponential growth of covariance values.

    • Erratic or unstable pool weight updates.

    • Overly reactive or overly rigid weight behavior.

  2. Length Mismatch: Missing length validation for _newData and movingAverage arrays could lead to out-of-bounds errors, causing transaction failures or undefined behavior.

Impact

  1. Explosive Growth in Covariance Values: Results in instability and increased protocol risk.

  2. Erratic Pool Behavior: Causes unpredictable and unreliable pool weight updates.

  3. Oscillatory or Divergent Covariance Updates: Invalidates portfolio performance and renders the system unreliable.

  4. Loss of Trust: Deters users and liquidity providers due to unreliable behavior.

  5. Potential Funds Loss: Leads to higher impermanent loss or exploitable conditions in the market.

Tools Used

Manual Review

Recommendations

Add a validation check to ensure lambda remains within a valid range before it is used:

+ require(lambda >= 0 && lambda <= 1, "Invalid lambda value");

Or, for fixed-point arithmetic:

+ require(lambda >= 0 && lambda <= 1e18, "Invalid lambda value");

Additionally, ensure that array lengths are validated before processing to avoid out-of-bounds errors. For example:

+ require(_newData.length >= _poolParameters.numberOfAssets, "Invalid new data length");
+ require(_poolParameters.movingAverage.length >= 2 * _poolParameters.numberOfAssets, "Invalid moving average length");
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.

Give us feedback!