QuantAMM

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

Initial oracle setup validation lacks check for oracle-to-asset count matching

Summary

UpdateWeightRunner's oracle setup validation lacks proper checks for oracle-to-asset count matching, leading to runtime failures during weight updates when oracles are missing for some assets.

Vulnerability Details

When deploying new pool deployer provides oracle sets (primary oracle + optional backup oracles) to be used for each asset. During pool setup process, various oracle checks are performed:

  • oracle for at least one asset is provided, checked by QuantAMMWEightedPool here

  • oracle for at least one asset is provided, checked by UpdateWeightRunner here

  • all provided oracles are approved, and there is at least one oracle at every existing array index, checked by UpdateWeightRunner here

But there is NO check that every pool asset has at least 1 oracle assigned.

Let's assume pool has 5 assets. It is possible to provide oracles for 4 assets only. Pool deployment and initialization process will be successful in spite of the misconfig.

Consequence of this misconfig is that every attempt to update weights by calling performUpdate will fail.

First oracles will be invoked in _getData function to collect prices for all 4 configured oracles:

function _getData(address _pool, bool internalCall) private view returns (int256[] memory outputData) {
// ...
outputData = new int256[](oracleLength);
for (uint i; i < oracleLength; ) {
// ...
outputData[i] = oracleResult.data;
}
}

Resulting data array is of length 4 since there are only 4 oracles configured. Later this data is used in _calculateQuantAMMMovingAverage and here TX will fail due to out of bounds array access (while doing calculation for 5th asset):

function _calculateQuantAMMMovingAverage(
int256[] memory _prevMovingAverage,
int256[] memory _newData,
int128[] memory _lambda,
uint _numberOfAssets
) internal pure returns (int256[] memory) {
// ...
for (uint i; i < _numberOfAssets; ) {
// @audit In our example there are 5 assets. So at index 4 code will try to access out-of-bounds array element of _newData
newMovingAverage[i] = movingAverageI + oneMinusLambda.mul(_newData[i] - movingAverageI);
unchecked {
++i;
}
}

Every attempt to performUpdate will fail and additionally, there is no way to update oracles for a specific pool to set proper config. So pool is permanently bricked in a way that core feature of weights updates can not be performed.

Impact

If too few oracle sets are provided when creating new pool, pool will still be successfully deployed and initialized. But the core feature of weight updates will be permanently disabled due to the oracle misconfig. I consider this a medium risk vulnerability.

Tools Used

Manual code review

Recommendations

During initialization check that number of provided oracle sets matches the number of assets:

require(_poolSettings.oracles.length > 0, "NOPROVORC");
+require(_poolSettings.oracles.length == _poolSettings.assets.length, "Wrong number of oracle sets provided");
Updates

Lead Judging Commences

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

Give us feedback!