QuantAMM

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

Weights within the range of 0 > weight <= 1e18 are treated as invalid. TFMM may yield incorrect results and possible arbitrage exploit issues.

Summary

In the PowerChannelUpdateRule contract, there's an external pure function called validParameters which can be used to validate a weight parameters. However, it's currently treating valid parameters within the range 0 > weight <= 1e18 as invalid parameters.

Vulnerability Details

PowerChannelUpdateRule::validParameters:

function validParameters(int256[][] calldata parameters) external pure override returns (bool valid) {
if (
(parameters.length == 2 || (parameters.length == 3 && parameters[2].length == 1))
&& (parameters[0].length > 0)
&& (parameters[0].length == 1 && parameters[1].length == 1 || parameters[1].length == parameters[0].length)
) {
valid = true;
for (uint256 i; i < parameters[0].length;) {
if (!(parameters[0][i] > 0)) {
valid = false;
break;
}
unchecked {
++i;
}
}
for (uint256 i; i < parameters[1].length;) {
// @info: seems like the coditional should be inverted therefore maybe requires
// negation of the condition
@> if (parameters[1][i] <= ONE) {
valid = false;
break;
}
unchecked {
++i;
}
}
return valid;
}
return false;
}

This function can be used to validate or invalidate weight parameters which can consequently potentially disrupt the protocol's intended core functionality.

Impact

If a valid parameter treate as an invalid parameter or vice versa then there could have potential vulnerabilities.

  1. Weights Not Summing to 100% (or 1e18)

    • Impact: The weights of all assets in a pool must sum to a normalized value (e.g., 1e18 for many protocols). If they do not:
      The pricing function (e.g., TFMM) might fail or yield incorrect results.
      The pool might not behave predictably during swaps, leading to price inaccuracies.

    • Consequence:
      Arbitrage Exploits: Traders could exploit mispriced assets to drain the pool.
      LP Losses: Liquidity providers might suffer impermanent loss or fail to earn expected fees due to the misconfigured pool.

  2. Out-of-Range Weights

    • Impact: Weights might be too low (e.g., close to 0) or too high (e.g., greater than the total normalized value):
      Extremely low weights could make certain assets nearly untradable, leading to illiquidity.
      Extremely high weights could overly concentrate liquidity in a single asset, reducing diversification and increasing risk.

    • Consequence:
      Liquidity Imbalance: The pool could favor one asset, creating inefficiency for traders and LPs.
      Increased Risk Exposure: A highly weighted asset's volatility could disproportionately impact the pool.

  3. Transaction Reversions

    • Impact: Most well-designed smart contracts include checks to prevent invalid parameters. For example:
      Ensure weights are within valid bounds (e.g., 0 <= weight <= 1e18).
      Ensure weights sum to 1e18.

    • Consequence:
      The transaction would fail and revert, wasting gas fees for the user.
      Operational delays in updating pool weights or performing other related functions.

  4. Failed Rebalancing

    • Impact: Pools rely on weights for rebalancing liquidity across assets. Invalid weights disrupt this process:
      Weight update rules (e.g., covariance-based or mean-variance rules) depend on valid inputs to calculate optimal weights.

    • Consequence:
      Inefficient Rebalancing: The pool might fail to adapt to market conditions, reducing profitability.
      Increased Impermanent Loss: LPs may lose out on potential gains due to mismanaged asset allocation.

Tools Used

Manual Review

Recommendations

We're just only missing a negation syntax to make if check condition a valid condition. One possible solution is given below:

PowerChannelUpdateRule::validParameters:

function validParameters(int256[][] calldata parameters) external pure override returns (bool valid) {
if (
(parameters.length == 2 || (parameters.length == 3 && parameters[2].length == 1))
&& (parameters[0].length > 0)
&& (parameters[0].length == 1 && parameters[1].length == 1 || parameters[1].length == parameters[0].length)
) {
valid = true;
for (uint256 i; i < parameters[0].length;) {
if (!(parameters[0][i] > 0)) {
valid = false;
break;
}
unchecked {
++i;
}
}
for (uint256 i; i < parameters[1].length;) {
- if (parameters[1][i] <= ONE) {
+ if (!(parameters[1][i] <= ONE)) {
valid = false;
break;
}
unchecked {
++i;
}
}
return valid;
}
return false;
}
Updates

Lead Judging Commences

n0kto Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!