QuantAMM

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

Pool Update Denial of Service Through Last Run Time Manipulation

Summary

Known Issues Section where the permission required for this attack is documented as in-scope.

In technical code terms for pool creator trust levels have three expected types:
1. Balancer V2 style "managed pool" using QuantAMMWeightedPool - poolRegistry on the pool enables manual setting of weights via the update weight runner. The pool creator is trusted.
2. QuantAMM Protocol Pool with pool creator enabled to manually change weights in approvedPoolActions. The pool creator is trusted.
3. QuantAMM Protocol Pool where pool creator is not enabled to manually change weights in approvedPoolActions
3 is the standard case for QuantAMM Protocol Pools, and for case 3 a pool creator is deemed untrusted and any manipulation of the pool by the pool creatoe is in scope.

The InitialisePoolLastRunTime function in the UpdateWeightRunner contract allows pool owners to set an arbitrary last run time, which can be exploited to cause a denial of service in the weight update mechanism. This can be leveraged to gain unfair advantages by the pool owner where they have total control over when the pool is updated.

Vulnerability Details

In the UpdateWeightRunner contract, the InitialisePoolLastRunTime function allows setting the lastPoolUpdateRun timestamp without validation:

function InitialisePoolLastRunTime(address _poolAddress, uint40 _time) external {
uint256 poolRegistryEntry = approvedPoolActions[_poolAddress];
//current breakglass settings allow pool creator trigger. This is subject to review
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 last run time");
}
poolRuleSettings[_poolAddress].timingSettings.lastPoolUpdateRun = _time;
emit PoolLastRunSet(_poolAddress, _time);
}

A malicious pool owner can set this value to type(uint40).max or any value greater then block.timestamp, which would cause an underflow in the performUpdate function. This effectively prevents the pool from being updated, as the time delta calculations would fail.

require(
block.timestamp - settings.timingSettings.lastPoolUpdateRun >= settings.timingSettings.updateInterval,
"Update not allowed"
);

The vulnerability is particularly concerning because:

  1. Pool owners with the ability to set the last run time are considered untrusted according to the scope

  2. The timestamp parameter is not validated

  3. The function can be called multiple times thus the attack can be repeated

  4. The impact extends beyond just weight updates, affecting pool performance and LP positions

Impact

DOS and **Reintroduce IL (**Impermanent loss) to the pool which is one of the core problems this protocol is trying to solve.

The vulnerability allows malicious pool owners to:

  1. Prevent weight updates from executing properly

  2. Create windows of opportunity for MEV exploitation

  3. Collect fees earlier than intended through likely LP exits

Tools Used

Manual Review

Recommendations

Add validation checks to prevent malicious timestamp values:

function InitialisePoolLastRunTime(address _poolAddress, uint40 _time) external {
// ... existing permission checks ...
// Ensure time is not in the future
require(_time <= uint40(block.timestamp), "Invalid timestamp");
poolRuleSettings[_poolAddress].timingSettings.lastPoolUpdateRun = _time;
emit PoolLastRunSet(_poolAddress, _time);
}

The recommended fix:

  1. Adds reasonable bounds for the timestamp value

  2. Prevents DOS attacks through timestamp manipulation

  3. Maintains the intended functionality for legitimate pool operations

  4. Protects LP interests by ensuring continuous pool updates

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.