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

Zero profit_max_unlock_time Allowed

Summary

The ScrvusdOracleV2 contract lacks validation for the profit_max_unlock_time parameter, allowing it to be set to zero. This results in division-by-zero errors in critical calculations, halting oracle functionality and destabilizing dependent systems.

Vulnerability Details

Affected Code

File: contracts/scrvusd/oracles/ScrvusdOracleV2.vy
Function: update_profit_max_unlock_time
Issue: Missing check for _profit_max_unlock_time > 0.

@external
def update_profit_max_unlock_time(_profit_max_unlock_time: uint256, _block_number: uint256) -> bool:
access_control._check_role(UNLOCK_TIME_VERIFIER, msg.sender)
# Missing: assert _profit_max_unlock_time > 0
self.profit_max_unlock_time = _profit_max_unlock_time
return prev_value != _profit_max_unlock_time

code: https://github.com/CodeHawks-Contests/2025-03-curve/blob/198820f0c30d5080f75073243677ff716429dbfd/contracts/scrvusd/oracles/ScrvusdOracleV2.vy#L333-L348

Root Cause

The update_profit_max_unlock_time function permits _profit_max_unlock_time = 0. When used in _obtain_price_params, this causes division by zero:

period: uint256 = self.profit_max_unlock_time # If 0, division fails below
number_of_periods: uint256 = (parameters_ts - params.last_profit_update) // period # REVERT

code: https://github.com/CodeHawks-Contests/2025-03-curve/blob/198820f0c30d5080f75073243677ff716429dbfd/contracts/scrvusd/oracles/ScrvusdOracleV2.vy#L236-L252

Impact

Division-by-zero errors will revert price calculations, freezing the oracle.

Tools Used

  • Manual Code Review: Identified missing validation in state-changing functions.

Recommendations

Fix Implementation

Add an assertion to enforce _profit_max_unlock_time > 0:

@external
def update_profit_max_unlock_time(_profit_max_unlock_time: uint256, _block_number: uint256) -> bool:
access_control._check_role(UNLOCK_TIME_VERIFIER, msg.sender)
assert _profit_max_unlock_time > 0, "Invalid period: zero" # <--- FIX
self.profit_max_unlock_time = _profit_max_unlock_time
return prev_value != _profit_max_unlock_time
Updates

Lead Judging Commences

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

[invalid] finding-missing-proof-content-validation

- See [here]([https://github.com/CodeHawks-Contests/2025-03-curve?tab=readme-ov-file#blockhash-oracle)](https://github.com/CodeHawks-Contests/2025-03-curve?tab=readme-ov-file#blockhash-oracle) on how it is used to verify storage variable - All state roots and proofs must be verified by the OOS `StateProofVerifier` inherited as `Verifier` (where the price values and params are extracted), so there is no proof that manipulating timestamp/inputs can affect a price update - It is assumed that the OOS prover will provide accurate data and the OOS verifier will verify the prices/max unlock time to be within an appropriate bound/values - There is a account existance check in L96 of `ScrvusdVerifierV1.sol`, in which the params for price updates are extracted from

Support

FAQs

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