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

Underflow vulnerability in ScrvusdOracleV2.vy::_smoothed_price function

Summary

This function smooths price changes to prevent sudden large fluctuations. It calculates a maximum allowed price change (max_change) based on max_price_increment, Time (block.timestamp - last_update) and last_price

but while calculating raw price, it can result in underflow if the last price is greater than raw price and max_change variable then this will cause underflow

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

if unsafe_sub(raw_price + max_change, last_price) > 2 * max_change:

Vulnerability Details

If raw_price + max_change < last_price, then unsafe_sub(raw_price + max_change, last_price) underflows. Instead of returning a small negative number, it wraps around to a very large value, leading to incorrect price calculations.

Impact

The function will return a wildly incorrect price due to the huge wrapped value. If the contract relies on the smoothed price for key logic, underflows can break calculations and prevent proper execution. the condition > 2 * max_change may always evaluate true, forcing incorrect price smoothing.

Let us resume following prices

last_price = 500

  • raw_price = 200

  • max_change = 50

raw_price+max_change=200+50=250

unsafe_sub(raw_price + max_change, last_price)

since 250<500

this will underflow , wrapping around to:

2^256−(500−250)=2^256−250 which is a huge number close to 2^256.

Comparing it with 2×max_change=2×50=100

Since 2^256 - 250 is always greater than 100, the condition:

if unsafe_sub(raw_price + max_change, last_price) > 2 * max_change will be evaluated to true

Since the condition is true so the below code

return last_price + max_change if raw_price > last_price else last_price - max_change

will provide raw_price (200) < last_price (500), so we execute:

return last_price - max_change

500−50=450

Instead of returning raw_price (200), the function incorrectly smooths it to 450.

This is caused by underflow in unsafe_sub

Tools Used

Manual Review

Recommendations

We can replace the line of code with the following code for preventing underflow

  • If raw_price + max_change < last_price, it prevents subtraction and returns 0 otherwise it will perform normal calculation. This will ensure only real price changes beyond 2 * max_change trigger smoothing logic.

safe_diff: uint256 = 0 if raw_price + max_change < last_price else (raw_price + max_change) - last_price
if safe_diff > 2 * max_change:
return last_price + max_change if raw_price > last_price else last_price - max_change
return raw_price
Updates

Lead Judging Commences

0xnevi Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

[invalid] finding-unsafe-sub-underflow

If underflow occurs, it must have meant that `raw_price` has deviated from `last_price` by more than `max_change`, meaning it is correct to restrict the `last_price` increment to `max_change`

Support

FAQs

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