QuantAMM

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

Missing Gradient Initialization in DifferenceMomentumUpdateRule Contract Leading to Incorrect Weight Calculations and Pool Instability.

Summary

In the DifferenceMomentumUpdateRule contract, the function _setInitialIntermediateValues is responsible for initializing the intermediate values for the pool, including setting the moving averages. However, it does not call the required _setGradient function from the QuantAMMGradientBasedRule contract, which is essential for initializing the gradient during pool creation.

Vulnerability Details:

The vulnerability arises from the DifferenceMomentumUpdateRule contract, where the _setInitialIntermediateValues function is intended to initialize various intermediate values for a pool, such as the moving averages. However, the function fails to call the required _setGradient function from the QuantAMMGradientBasedRule contract, which is responsible for initializing the gradient.

Here’s the relevant code snippet:

_setInitialIntermediateValues in DifferenceMomentumUpdateRule contract:

function _setInitialIntermediateValues(
address _poolAddress,
int256[] memory _initialValues,
uint256 _numberOfAssets
) internal override {
require(_initialValues.length == _numberOfAssets, "Invalid initial values");
//to avoid incorrect access to base MathMovingAverage, we need to set the moving average here
uint256 movingAverageLength = shortMovingAverages[_poolAddress].length;
if (movingAverageLength == 0 || _initialValues.length == _numberOfAssets) {
//should be during create pool
shortMovingAverages[_poolAddress] = _quantAMMPack128Array(_initialValues);
@> // @info: forgot to call _setGradient here
} else {
revert("Invalid set moving avg");
}
}

_setGradient in QuantAMMGradientBasedRule contract:

function _setGradient(address poolAddress, int256[] memory _initialValues, uint256 _numberOfAssets) internal {
uint256 storeLength = intermediateGradientStates[poolAddress].length;
if ((storeLength == 0 && _initialValues.length == _numberOfAssets) || _initialValues.length == storeLength) {
//should be during create pool
intermediateGradientStates[poolAddress] = _quantAMMPack128Array(_initialValues);
} else {
revert("Invalid set gradient");
}
}

Impact:

  1. Missing Gradient Initialization:

    • The gradient is a vital component for the proper functioning of the pool, particularly for updating the weights using momentum and trend analysis.

    • If the gradient is not initialized, it will lead to incorrect weight calculations. This will negatively impact the pool’s optimization, possibly resulting in inefficient or incorrect weight adjustments.

  2. Incorrect Weight Calculations:

    • The gradient is used to determine how the pool’s asset weights should be updated. Without initializing the gradient, the weight update logic is incomplete, which can cause the weights to remain static or deviate from optimal values.

  3. Pool Instability:

    • If the gradient is not properly set, the pool may not adapt correctly to market changes. This could lead to instability in pool behavior, potentially triggering inefficiencies, like increased impermanent loss or poor liquidity management.

  4. Contract Malfunctions or Reverts:

    • In some scenarios, the lack of gradient initialization could trigger revert errors in subsequent transactions or interactions with the contract, resulting in a Denial of Service (DoS) for users or other system failures.

  5. Exposure to Market Risks:

    • A pool with improperly initialized gradients may be vulnerable to market manipulation. Malicious actors could take advantage of this weakness, leading to potential exploitation of the pool’s assets or trading mechanism.

Root Cause:

The root cause of this issue is the failure to call the required _setGradient function from the QuantAMMGradientBasedRule contract during the initialization of the pool. Without this step, the gradient that is necessary for proper weight adjustments is not initialized, which compromises the entire weight calculation process.

Tools Used

Manual Review

Recommendations

To resolve this issue, the following line should be added in the _setInitialIntermediateValues function to properly initialize the gradient during pool creation:

// Call _setGradient to initialize the gradient
_setGradient(_poolAddress, _initialValues, _numberOfAssets);

This will ensure that the gradient is properly initialized along with the moving averages and prevent any issues related to missing gradient initialization.

So do the following updatation in the _setInitialIntermediateValues function...

function _setInitialIntermediateValues(
address _poolAddress,
int256[] memory _initialValues,
uint256 _numberOfAssets
) internal override {
require(_initialValues.length == _numberOfAssets, "Invalid initial values");
//to avoid incorrect access to base MathMovingAverage, we need to set the moving average here
uint256 movingAverageLength = shortMovingAverages[_poolAddress].length;
if (movingAverageLength == 0 || _initialValues.length == _numberOfAssets) {
//should be during create pool
shortMovingAverages[_poolAddress] = _quantAMMPack128Array(_initialValues);
+ _setGradient(_poolAddress, _initialValues, _numberOfAssets);
} else {
revert("Invalid set moving avg");
}
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!