QuantAMM

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

The `computeBalance` function may revert because the `setWeights` function doesn't check the boundary of the normalized weight

Summary

As per the WeightedMath , the normalized weight has a boundary which is between 0.01 and 0.99. If the normalized weight set by the setWeights function breaks this boundary, the computeBalance will revert due to math overflow.

Vulnerability Details

The comments in WeightedMath imply that the boundary of the normalized weights is between 0.01 and 0.99:

// In computing `balance^normalizedWeight`, `log(balance) * normalizedWeight` must fall within the `pow` function
// bounds described above. Since 0.01 <= normalizedWeight <= 0.99, the balance is constrained to the range between
// e^(ExpMin) and e^(ExpMax).

However, the boundary of the normalized weights is not checked in the setWeights function in QuantAMMWeightedPool contract:

function setWeights(
int256[] calldata _weights,
address _poolAddress,
uint40 _lastInterpolationTimePossible
) external override {
require(msg.sender == address(updateWeightRunner), "ONLYUPDW");
require(_weights.length == _totalTokens * 2, "WLDL"); //weight length different
if (_weights.length > 8) {
int256[][] memory splitWeights = _splitWeightAndMultipliers(_weights);
_normalizedFirstFourWeights = quantAMMPack32Array(splitWeights[0])[0];
_normalizedSecondFourWeights = quantAMMPack32Array(splitWeights[1])[0];
} else {
_normalizedFirstFourWeights = quantAMMPack32Array(_weights)[0];
}
//struct allows one SSTORE
poolSettings.quantAMMBaseInterpolationDetails = QuantAMMBaseInterpolationVariables({
lastPossibleInterpolationTime: _lastInterpolationTimePossible,
lastUpdateIntervalTime: uint40(block.timestamp)
});
emit WeightsUpdated(_poolAddress, _weights);
}

If the weights are out of bounds, this may lead to an overflow in the WeightedMath calculation. For example, the computeBalance function will revert due to the math overflow.

Poc

Adding the following test case in QuantAMMWeightedPool2TokenTest , it sets the weights to 0.0006 and 0.9994

function testComputeBalanceInitial() public {
QuantAMMWeightedPoolFactory.NewPoolParams memory params = _createPoolParams();
(address quantAMMWeightedPool, ) = quantAMMWeightedPoolFactory.create(params);
int256[] memory newWeights = new int256[]();
newWeights[0] = 0.0006e18;
newWeights[1] = 0.9994e18;
newWeights[2] = 0e18;
newWeights[3] = 0e18;
vm.prank(address(updateWeightRunner));
QuantAMMWeightedPool(quantAMMWeightedPool).setWeights(
newWeights,
quantAMMWeightedPool,
uint40(block.timestamp + 5)
);
uint256[] memory balances = new uint256[]();
balances[0] = 1000e18;
balances[1] = 2000e18;
uint256 newBalance = QuantAMMWeightedPool(quantAMMWeightedPool).computeBalance(balances, 0, uint256(1.2e18));
//assertEq(newBalance, 1355.091881588694578000e18);
}

run forge test --match-test testComputeBalanceInitial

Failing tests:
Encountered 1 failing test in test/foundry/QuantAMMWeightedPool2Token.t.sol:QuantAMMWeightedPool2TokenTest
[FAIL: ProductOutOfBounds()] testComputeBalanceInitial() (gas: 12465744)

We can see that the computeBalance will revert due to math overflow.

Impact

The impact is HIGH because this will dos the computeBalance function.

The likelihood is LOW because the weight should be less than 0.01 or greater than 0.99, which is not a normal case.

As a result, the severity should be MEDIUM.

Tools Used

Manual Review

Recommendations

In QuantAMMWeightedPool contract, consider adding a check on the weight boundaries in the setWeights function.

Updates

Lead Judging Commences

n0kto Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_setWeights_no_boundaries_0.99_0.01_lead_to_revert_WeightedMath

Likelihood: Low, this will only happen in extreme case. Impact: High, DoS computeBalance which is used to add liquidity for single tokens

Appeal created

angrymustacheman Auditor
4 months ago
atharv181 Auditor
4 months ago
n0kto Lead Judge
4 months ago
n0kto Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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