Summary
Both setWeightsManually and setIntermediateValuesManually, the contract assumes that the _poolAddress parameter corresponds to a valid and approved pool, and that the oracles associated with the pool are operational and up-to-date. However:
Vulnerability Details
function setWeightsManually(
int256[] calldata _weights,
address _poolAddress,
uint40 _lastInterpolationTimePossible,
uint _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");
}
for (uint 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);
}
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/UpdateWeightRunner.sol#L559-L594
function setIntermediateValuesManually(
address _poolAddress,
int256[] memory _newMovingAverages,
int256[] memory _newParameters,
uint _numberOfAssets
) external {
uint256 poolRegistryEntry = approvedPoolActions[_poolAddress];
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 intermediate values");
}
IUpdateRule rule = rules[_poolAddress];
rule.initialisePoolRuleIntermediateValues(_poolAddress, _newMovingAverages, _newParameters, _numberOfAssets);
emit SetIntermediateValuesManually(
msg.sender,
_poolAddress,
_newMovingAverages,
_newParameters,
_numberOfAssets
);
}
}
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/UpdateWeightRunner.sol#L595-L625
Impact
Malicious or unauthorized pool addresses could be passed to the functions, potentially allowing unauthorized updates.
Updates based on outdated or malfunctioning oracles could cause incorrect calculations, leading to pool instability and financial losses.
Tools Used
Recommendations
Validate Pool Existence: Introduce a registry of approved pools.
validate the _poolAddress before using it.
Add a function to check the staleness of oracles.
Call the validation function before using the oracle.
include pool and oracle checks:
require(approvedPools[_poolAddress], "Pool address not approved");
for (uint i = 0; i < poolOracles[_poolAddress].length; i++) {
validateOracle(poolOracles[_poolAddress][i]);
}
function setWeightsManually(
int256[] calldata _weights,
address _poolAddress,
uint40 _lastInterpolationTimePossible,
uint _numberOfAssets
) external {
require(approvedPools[_poolAddress], "Pool address not approved")
for (uint i = 0; i < poolOracles[_poolAddress].length; i++) {
validateOracle(poolOracles[_poolAddress][i]);
}
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")
}
for (uint i; i < _weights.length; i++) {
if (i < _numberOfAssets) {
require(_weights[i] > 0, "Negative weight not allowed");
require(_weights[i] < 1e18, "Weight greater than 1 not allowed");
}
}
IQuantAMMWeightedPool(_poolAddress).setWeights(_weights, _poolAddress, _lastInterpolationTimePossible);
emit SetWeightManual(msg.sender, _poolAddress, _weights, _lastInterpolationTimePossible);
}