QuantAMM

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

For scalar kappa and lamda, the most essential check of computed weight greater than ‘0’ is missing in all the 6 update rules.

Summary

The the function _getWeights in all the update rules viz. ChannelFollowingUpdateRule.sol, PowerChannelUpdateRule.sol, MomentumUpdateRule.sol, AntimomentumUpdateRule.sol, MinimumVarianceUpdateRule.sol and DifferenceMomentumUpdateRule.sol do not feature the necessary checks on the computed new weights.

Vulnerability Details

On the computed new weights, some of the basic minimum checks, viz.

(i) Each computed weight > 0; //must case.
(ii) Each computed weight < 1; //preferred case.
(iii) Sum of all the weights of a pool = 1; (This can be modified to something like (1 - Sum of all the weights of a pool) < 1e9; (or some other convenient small acceptable threshold). //preferred case.
(iv) Each computed weight < absoluteWeightGuardRail; //can be avoided.
should be done to have proper valuation of the pool, etc.

In the codebase, at present no checks are done on the computed weights for the cases of scalar kappa or scalar lambda in any of the six update rules mentioned in summary section, including even the most important check of (computed weight > 0). Only the check (i) is present for the cases where each asset has separate lambda or kappa. At least the checks (i) and (ii) should be included for all the computed new weights.

A. In the function _getWeights in ChannelFollowingUpdateRule.sol, these checks are required at Line number 232
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/ChannelFollowingUpdateRule.sol#L232

require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");

should be added.

In line #249, the require statement considers the new weight = 0 as Valid weight which is incorrect. new weight = 0 implies the corresponding asset of the pool as virtually absent or of no value. This too need to be corrected by replacing
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/ChannelFollowingUpdateRule.sol#L249 with

require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");

B. Observation similar to the above observation is seen in the function _getWeights in PowerChannelUpdateRule.sol. For the scalar kappa case, here too, the line number #128 can be modified from
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/PowerChannelUpdateRule.sol#L128
to

require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");
unchecked {

Similarly for the vector kappa case, the line numbers #149 and #150
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/PowerChannelUpdateRule.sol#L149-L150
can be modified to

newWeightsConverted[locals.i] = locals.res;
require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");

C. The similar issue is present in the function _getWeights in MomentumUpdateRule.sol. The recommendation too is similar to above. For the scalar kappa, the line number #106
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/MomentumUpdateRule.sol#L106
needs to be modified to

require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");

For the vector kappa case, the line numbers #128 to 129 need to be modified from
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/MomentumUpdateRule.sol#L128-L129

require(locals.res >= 0, "Invalid weight");
newWeightsConverted[locals.i] = locals.res;

to

newWeightsConverted[locals.i] = locals.res;
require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");

D. The similar issue is present in the function _getWeights in AntimomentumUpdateRule.sol. The recommendation too is similar to earlier mentioned. For the scalar kappa, the line number #102
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/AntimomentumUpdateRule.sol#L102
can be replaced with

require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");
unchecked {

For the vector kappa,the line numbers #120 and 121
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/AntimomentumUpdateRule.sol#L120-L121

require(res >= 0, "Invalid weight");
newWeightsConverted[locals.i] = res;

can be modified to

newWeightsConverted[locals.i] = locals.res;
require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");

E. The function _getWeights in MinimumVarianceUpdateRule.sol does not feature any checks on the computed new weights. The checks are essential here too. For the scalar lambda, the line number #61
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/MinimumVarianceUpdateRule.sol#L61
can be modified to

require(newWeightsConverted[i] > 0, "Invalid weight");
require(newWeightsConverted[i] < 1e18, "Invalid weight");
unchecked {

For the vector lambda, the line number #84
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/MinimumVarianceUpdateRule.sol#L84
can be modified to

require(newWeightsConverted[i] > 0, "Invalid weight");
require(newWeightsConverted[i] < 1e18, "Invalid weight");
unchecked {

F. In the function _getWeights in DifferenceMomentumUpdateRule.sol also, this issue persists. For the scalar kappa, the line number #127
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/DifferenceMomentumUpdateRule.sol#L127
can be modified to

require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");

For vector kappa, line number #150
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/rules/DifferenceMomentumUpdateRule.sol#L150
can be modified to

require(newWeightsConverted[locals.i] > 0, "Invalid weight");
require(newWeightsConverted[locals.i] < 1e18, "Invalid weight");
unchecked {

Impact

The likelihood of the weights crossing the requirements is generally low, but the impact is severe as it affects all the pool assets.

Tools Used

Manual review

Recommended Mitigation

Provided in the vulnerability section itself.

I would recommend even some modified values other than ‘0’ and ‘1’ in the case of (i) and (ii) respectively (say 0.02 and 0.7 depending on the number of assets in the pool, their relative strengths presently in the market, etc.), to be firmed up only after plenty of simulations. But arriving at any value has its own pros and cons.

Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

invalid_weights_can_be_negative_or_extreme_values

_clampWeights will check that these weights are positive and in the boundaries before writing them in storage.

Support

FAQs

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