DeFiLayer 1Layer 2
14,723 OP
View results
Submission Details
Severity: medium
Invalid

Precision Loss in Smoothed Price Calculation

Summary

The _smoothed_price function uses a linear approximation to compute the maximum allowed price change, which inherently involves integer division and truncation of fractional components. Over multiple updates, this can lead to cumulative rounding errors that may be exploited to gradually manipulate the oracle's reported price.

Vulnerability Details

https://github.com/CodeHawks-Contests/2025-03-curve/blob/main/contracts/scrvusd/oracles/ScrvusdOracleV2.vy#L155

def _smoothed_price(last_price: uint256, raw_price: uint256) -> uint256:
# Ideally should be (max_price_increment / 10**18) ** (block.timestamp - self.last_update)
# Using linear approximation to simplify calculations
max_change: uint256 = (
self.max_price_increment * (block.timestamp - self.last_update) * last_price // 10**18
)
# -max_change <= (raw_price - last_price) <= max_change
if unsafe_sub(raw_price + max_change, last_price) > 2 * max_change:
return last_price + max_change if raw_price > last_price else last_price - max_change
return raw_price

The function calculates the maximum change (max_change) as:

max_change: uint256 = (
self.max_price_increment * (block.timestamp - self.last_update) * last_price // 10**18
)

It then clamps the raw price if the difference between raw_price and last_price exceeds max_change.

Unlike exponential smoothing, which would naturally account for the time-dependent change using a multiplicative factor (i.e., last_price * e^(rate * time_delta)), the linear method truncates fractional differences. This design choice is made for simplicity but introduces unavoidable rounding errors.

When small deviations in price occur repeatedly—whether due to market conditions or attacker-induced manipulation—each update may lose a small fractional value due to truncation. Over many updates, these losses can accumulate, causing the smoothed price to diverge from the ideal value.

Impact

The cumulative error may lead to an undervalued or overvalued price relative to the actual underlying asset value. Although the error per update might be minimal, its gradual accumulation can result in significant financial discrepancies that harm liquidity providers.

Tools Used

Manual Review

Recommendations

Replace the linear approximation with an exponential model such as:

new_price = last_price * exp(rate * time_delta)

where rate is derived from max_price_increment to better capture compounding effects and reduce truncation errors.

Updates

Lead Judging Commences

0xnevi Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality
Assigned finding tags:

[invalid] finding-precision-loss

All values will be scaled to a combined of 36 decimals before division (be it price-related values or totalSupply). Considering the 18 decimals of all values, no realistic values were presented in any duplicates to proof a substantial impact on precision loss.

Support

FAQs

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