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

Incorrect Multiplication in MAX_V2_DURATION Leading to Misaligned Duration Calculation

Summary

The MAX_V2_DURATION constant in the ScrvusdOracleV2.vy contract is intended to represent a maximum duration of 4 years in weeks. However, due to an incorrect multiplication, it instead calculates a period of 192 years, leading to severe misalignment in time-sensitive calculations. This logical flaw can significantly impact financial computations, lockup periods, and reward distributions, potentially resulting in unintended behaviors in the contract's execution.

Vulnerability Details

Affected Code:

MAX_V2_DURATION: constant(uint256) = 4 * 12 * 4 # 4 years
  • The comment suggests that the intention is to define a period of 4 years.

  • The multiplication 4 * 12 * 4 is incorrectly structured:

    • 4 (years)

    • 12 (months per year)

    • 4 (???)

If this calculation were intended to represent 4 years in weeks, the correct formula should have been:

MAX_V2_DURATION: constant(uint256) = 4 * 52 # 4 years (in weeks)

However, in another part of the code, we see a conflicting definition:

self.max_v2_duration = 4 * 6 # half a year

The comment suggests it represents half a year (which is 26 weeks).

  • However, the formula 4 * 6 = 24 weeks, which is not exactly half a year.

Since 1 year = 52 weeks, half a year is:

52 / 2 = 26 weeks

This inconsistency raises concerns regarding whether MAX_V2_DURATION is ever properly used, or if certain logic relies on the incorrect value, leading to misalignment in time calculations.

Why is this problematic?

  • The computed value for MAX_V2_DURATION is 4 * 12 * 4 = 192 weeks (~3.7 years) instead of 4 * 52 = 208 weeks.

  • If MAX_V2_DURATION is mistakenly treated as months instead of weeks, it results in 192 years instead of 4 years.

  • Since this value limits iterations in loops and calculations in the contract (as seen in _obtain_price_params), misalignment could result in overflows, unnecessary looping, or improper fund distribution calculations.

@view
def _obtain_price_params(parameters_ts: uint256) -> PriceParams:
"""
@notice Obtain Price parameters true or assumed to be true at `parameters_ts`.
Assumes constant gain(in crvUSD rewards) through distribution periods.
@param parameters_ts Timestamp to obtain parameters for
@return Assumed `PriceParams`
"""
params: PriceParams = self.price_params
period: uint256 = self.profit_max_unlock_time
if params.last_profit_update + period >= parameters_ts:
return params
number_of_periods: uint256 = min(
(parameters_ts - params.last_profit_update) // period,
self.max_v2_duration, #=================================== it is used here
)
# locked shares at moment params.last_profit_update
gain: uint256 = (
params.balance_of_self * (params.total_idle + params.total_debt) // params.total_supply
)
params.total_idle += gain * number_of_periods
# functions are reduced from `VaultV3._process_report()` given assumptions with constant gain
for _: uint256 in range(number_of_periods, bound=MAX_V2_DURATION):## ====also used here
new_balance_of_self: uint256 = (
params.balance_of_self
* (params.total_supply - params.balance_of_self) // params.total_supply
)
params.total_supply -= (
params.balance_of_self * params.balance_of_self // params.total_supply
)
params.balance_of_self = new_balance_of_self
if params.full_profit_unlock_date > params.last_profit_update:
# copy from `VaultV3._process_report()`
params.profit_unlocking_rate = params.balance_of_self * MAX_BPS_EXTENDED // (
params.full_profit_unlock_date - params.last_profit_update
)
else:
params.profit_unlocking_rate = 0
params.full_profit_unlock_date += number_of_periods * period
params.last_profit_update += number_of_periods * period
return params

Impact

In _obtain_price_params, the loop uses MAX_V2_DURATION to iterate through price updates:

for _: uint256 in range(number_of_periods, bound=MAX_V2_DURATION):

If MAX_V2_DURATION is too large, this loop may execute far more times than expected, leading to gas exhaustion or unintended state changes.

Tools Used

Manual Code Review: Identified inconsistency between the comment and the actual multiplication.

Recommendations

Fix the Multiplication Error:

MAX_V2_DURATION: constant(uint256) = 4 * 52 # Correctly represents 4 years in weeks
Updates

Lead Judging Commences

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

[invalid] finding-MAX_V2_DURATION

This is simply an approximation. I don't believe there is any incorrect logic here, given as long as this duration of growth is consistently applied, there will arguably be no incorrect oracle prices here. Additionally, I highly doubt there will be a instance where 48 weeks has passed since the last update.

Support

FAQs

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