QuantAMM

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

uint40 vs uint256 Timestamp Type Mismatch in computeBalance() Causes Balance Computation Errors When Block Timestamp Exceeds uint40

Summary

The computeBalance function exhibits inconsistent handling of timestamps that could lead to serious calculation errors. The function uses block.timestamp in two different ways:

  1. Cast to uint40: uint40 multiplierTime = uint40(block.timestamp)

  2. Raw uint256: if (block.timestamp >= lastInterpolationTime)

This inconsistent type handling creates a potential vulnerability where the timestamp comparison and the actual value used in calculations could disagree. Since lastInterpolationTime is stored as a uint40, but compared against the full uint256 block.timestamp, the function could enter incorrect logic branches when timestamps exceed uint40 maximum value (approximately 35 years).

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

uint40 multiplierTime = uint40(block.timestamp);
uint40 lastInterpolationTime = poolSettings.quantAMMBaseInterpolationDetails.lastPossibleInterpolationTime;
if (block.timestamp >= lastInterpolationTime) {
//we have gone beyond the first variable hitting the guard rail. We cannot interpolate any further and an update is needed
multiplierTime = lastInterpolationTime;
}
unchecked {
uint256 timeSinceLastUpdate = uint256(
multiplierTime - poolSettings.quantAMMBaseInterpolationDetails.lastUpdateIntervalTime
);
return
WeightedMath.computeBalanceOutGivenInvariant(
balancesLiveScaled18[tokenInIndex],
_getNormalizedWeight(tokenInIndex, timeSinceLastUpdate, _totalTokens),
invariantRatio
);
}

The impact of this bug manifests in several ways. First, weight calculations could use incorrect time intervals due to the mismatch between timestamp representations. This directly affects the pool's balance computations, potentially leading to incorrect pricing for trades. The weight adjustment mechanism, which is fundamental to the pool's operation, could malfunction as it relies on accurate time measurements for interpolation. This vulnerability is particularly severe because it affects core pool operations including swaps and liquidity management.

Recommended Mitigation Steps

To address this vulnerability, the code should be modified to ensure consistent timestamp handling throughout the function. This involves standardizing the use of uint40 for all timestamp operations. The function should first cast the block.timestamp to uint40 and use this value consistently for all comparisons and calculations.

The recommended implementation should handle timestamps as follows:

function computeBalance(
uint256[] memory balancesLiveScaled18,
uint256 tokenInIndex,
uint256 invariantRatio
) external view returns (uint256 newBalance) {
uint40 currentTime = uint40(block.timestamp);
uint40 multiplierTime = currentTime;
uint40 lastInterpolationTime = poolSettings.quantAMMBaseInterpolationDetails.lastPossibleInterpolationTime;
if (currentTime >= lastInterpolationTime) {
multiplierTime = lastInterpolationTime;
}
// ... rest of the function
}

Additionally, documentation should be added to clarify the uint40 usage and its implications for timestamp handling.

// timestamps are stored as uint40 to save gas, sufficient until year ~2078
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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