QuantAMM

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

Unbounded Time Delta in Weight Calculations Enables Pool Manipulation and Extreme Price Shifts

Summary

The calculateBlockNormalisedWeight function uses an unbounded timeSinceLastUpdate parameter to calculate weight adjustments:

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/QuantAMMWeightedPool.sol#L527

function calculateBlockNormalisedWeight(
int256 weight,
int256 multiplier,
uint256 timeSinceLastUpdate
) internal pure returns (uint256) {
int256 multiplierScaled18 = multiplier * 1e18;
if (multiplier > 0) {
return uint256(weight) + FixedPoint.mulDown(uint256(multiplierScaled18), timeSinceLastUpdate);
} else {
return uint256(weight) - FixedPoint.mulUp(uint256(-multiplierScaled18), timeSinceLastUpdate);
}
}

The absence of a maximum time delta constraint in weight calculations poses a significant risk to pool stability and security. When weight adjustments are calculated, the time since the last update is multiplied directly with the weight multiplier. In scenarios where updates are delayed or prevented for extended periods, this multiplication can result in dramatic weight shifts that far exceed normal operational parameters.

This vulnerability becomes particularly concerning in the context of automated market making, where weight ratios directly influence trading prices and pool behavior. An attacker could potentially manipulate update timing to force extreme weight changes, creating arbitrage opportunities or destabilizing the pool. The economic impact could be severe, as liquidity providers might suffer losses due to pool imbalances that deviate significantly from intended strategies.

The risk is compounded by the fact that the protocol's economic model assumes relatively frequent updates with moderate weight changes. The unbounded nature of time-based calculations breaks this assumption, potentially invalidating core economic security properties of the system.

Recommended Mitigation Steps

  1. Implement a maximum time delta constant:

uint256 private constant MAX_TIME_SINCE_UPDATE = 1 days; // Or another appropriate maximum
  1. Add validation in the calculation function:

function calculateBlockNormalisedWeight(
int256 weight,
int256 multiplier,
uint256 timeSinceLastUpdate
) internal pure returns (uint256) {
require(timeSinceLastUpdate <= MAX_TIME_SINCE_UPDATE, "Time delta exceeds maximum");
int256 multiplierScaled18 = multiplier * 1e18;
if (multiplier > 0) {
return uint256(weight) + FixedPoint.mulDown(uint256(multiplierScaled18), timeSinceLastUpdate);
} else {
return uint256(weight) - FixedPoint.mulUp(uint256(-multiplierScaled18), timeSinceLastUpdate);
}
}
  1. Consider implementing a progressive dampening mechanism for longer time periods to prevent extreme shifts:

uint256 effectiveTimeDelta = timeSinceLastUpdate > MAX_TIME_SINCE_UPDATE ?
MAX_TIME_SINCE_UPDATE : timeSinceLastUpdate;
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.