QuantAMM

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

poolRegistry fetched from the pool in setWeightsManually() may lead to issue in emergency situations

Summary

In the UpdateWeightRunner.sol:setWeightsManually() function poolRegistryEntry immutable variable is being fetched from pool. Unlike other functions, such as setIntermediateValuesManually() or InitialisePoolLastRunTime() which rely on the poolRegistry maintained in the UpdateWeightRunner.sol contract and can be modified by admin.

Vulnerability Details

This design flaw can restrict the flexibility and accessibility of updating weights manually in emergency situations.

UpdateWeightRunner.sol:setWeightsManually():

/// @notice Breakglass function to allow the admin or the pool manager to set the quantammAdmins weights manually
/// @param _weights the new weights
/// @param _poolAddress the target pool
/// @param _lastInterpolationTimePossible the last time that the interpolation will work
/// @param _numberOfAssets the number of assets in the pool
function setWeightsManually(
int256[] calldata _weights,
address _poolAddress,
uint40 _lastInterpolationTimePossible,
uint _numberOfAssets
) external {
//Fetched from pool
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");
}
//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
//CYFRIN L-02
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);
}

QuantAMMWeightedPool.sol:

///@dev the admin functionality enabled for this pool.
uint256 public immutable poolRegistry;
...
constructor(
NewPoolParams memory params,
IVault vault
) BalancerPoolToken(vault, params.name, params.symbol) PoolInfo(vault) Version(params.version) {
_totalTokens = params.numTokens;
updateWeightRunner = UpdateWeightRunner(params.updateWeightRunner);
quantammAdmin = updateWeightRunner.quantammAdmin();
//pool registry only set once
poolRegistry = params.poolRegistry;
require(params.poolDetails.length <= 50, "Limit exceeds array length");
for(uint i; i < params.poolDetails.length; i++){
require(params.poolDetails[i].length == 4, "detail needs all 4 [category, name, type, detail]");
}
poolDetails = params.poolDetails;
}

Impact

Inability to respond quickly in emergencies and potential lockout of quantAMM admin

Tools Used

Manual Review

Recommendations

Use poolRegistryEntry from the same UpdateWeightRunner.sol contract:

uint256 poolRegistryEntry = approvedPoolActions[_poolAddress];
Updates

Lead Judging Commences

n0kto Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
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.

Give us feedback!