QuantAMM

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

Bypassing Weight Validation with Zero _numberOfAssets Parameter

Summary

The setWeightsManually function has an issue that allows the new weights check to be bypassed if _numberOfAssets are 0.
This issue arises because the loop condition that validates _weights depends on _numberOfAssets, so if the _numberOfAssets are set 0 a _weights can be set greater than 1e18.

Vulnerability Details

The function setWeightsManually is called by Owner and it accepts _numberOfAssets as a parameter, which is used to validate the _weights array.
But this check can be bypassed simply by specifying _numberOfAssets as 0 and set _weights greater than 1e18.

In simple words this check has no effect and can be bypassed easily.

for (uint256 i; i < _weights.length; i++) {
if (i < _numberOfAssets) {
require(_weights[i] > 0, "Negative weight not allowed");
require(_weights[i] < 1e18, "greater than 1 weight not allowed");
}
}

POC: Add this in UpdateWeightRunner.t.sol

function test_bypass_setWeights() public {
int256[] memory weights = new int256[]();
weights[0] = 5e18; // Weight is greater than 1e18
weights[1] = 5e18;
weights[2] = 0;
weights[3] = 0;
mockPool.setPoolRegistry(16);
vm.startPrank(owner);
updateWeightRunner.setApprovedActionsForPool(address(mockPool), 16);
vm.stopPrank();
vm.startPrank(owner);
// number of assets are set to 0
updateWeightRunner.setWeightsManually(weights, address(mockPool), 6, 0);
vm.stopPrank();
}

Result:

Ran 1 test for test/foundry/UpdateWeightRunner.t.sol:UpdateWeightRunnerTest
[PASS] test_bypass_setWeights() (gas: 187861)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1.66ms (127.66µs CPU time)

If _numberOfAssets is set to 0, the condition i < _numberOfAssets is never true, and none of the weights are validated.
This bypass allows to set invalid weights that could destabilize the system or manipulate the pool.

Impact

This vulnerability can lead to:

  • bypass of Weight Validation a high weights negative weights or weights exceeding the allowed range can be passed unchecked.

  • system Instability Invalid weights could disrupt the balance of assets in the pool, potentially leading to financial losses or breaking the intended functionality.

Recommendations

Retrieve numberOfAssets from the Pool replace the _numberOfAssets parameter with a value weight.length devided by 2
because each weight array == number of tokens * 2.

function setWeightsManually(
int256[] calldata _weights,
address _poolAddress,
uint40 _lastInterpolationTimePossible,
- uint256 _numberOfAssets
) external {
uint256 poolRegistryEntry = QuantAMMWeightedPool(_poolAddress).poolRegistry();
if (poolRegistryEntry & MASK_POOL_OWNER_UPDATES > 0) {
require(msg.sender == poolRuleSettings[_poolAddress].poolManager, "ONLYMANAGER");
} else if (poolRegistryEntry & MASK_POOL_QUANTAMM_ADMIN_UPDATES > 0) {
require(msg.sender == quantammAdmin, "ONLYADMIN");
} else {
revert("No permission to set weight values");
}
+ // devide _weights.length by 2 because each _weight array == number of assets * 2;
+ uint256 _numberOfAssets = _weights.length / 2;
// though we try to keep manual overrides as open as possible for unknown unknows
// given how the math library works weights it is easiest to define weights as 18dp
// even though technically G3M works of the ratio between them so it is not strictly necessary
for (uint256 i; i < _weights.length; i++) {
if (i < _numberOfAssets) {
require(_weights[i] > 0, "Negative weight not allowed");
require(_weights[i] < 1e18, "greater than 1 weight not allowed");
}
}
IQuantAMMWeightedPool(_poolAddress).setWeights(_weights, _poolAddress, _lastInterpolationTimePossible);
emit SetWeightManual(msg.sender, _poolAddress, _weights, _lastInterpolationTimePossible);
}
Updates

Lead Judging Commences

n0kto Lead Judge 7 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.