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

Unchecked Total Supply in Price Calculation Leading to Division by Zero

Summary

The _raw_price function in ScrvusdOracleV2.vy performs a division operation without validating that the denominator (_total_supply) is non-zero. If _total_supply becomes zero due to invalid parameters or edge-case conditions, the transaction will revert, rendering the oracle temporarily unusable.

Vulnerability Details

The _raw_price function computes the price as:

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

Here, _total_supply is derived from PriceParams passed via update_price. If total_supply in PriceParams is zero (e.g., due to a misconfiguration, invalid state proof, or malicious input), the division // self._total_supply(...) will attempt to divide by zero, causing a runtime error and reverting the transaction.

Impact

A division-by-zero error will halt all oracle price updates and queries relying on _raw_price, disrupting dependent systems like stableswap-ng pools. While the likelihood of total_supply being zero under normal operation is low, it can occur due to:

  • Incorrectly formatted parameters in update_price,

  • Storage slot misalignment in verifier contracts after scrvUSD upgrades,

  • Maliciously crafted proofs.

Tools Used

Recommendations

Add a validation check in the update_price function to ensure total_supply is non-zero:

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

@external
def update_price(...):
# ... existing code ...
assert _parameters[2] > 0, "Invalid total_supply"
# ... rest of the code ...

Alternatively, handle the edge case in _raw_price by reverting with a descriptive error:

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

@view
def _raw_price(...) -> uint256:
supply: uint256 = self._total_supply(...)
assert supply > 0, "Zero total_supply"
return self._total_assets(...) * 10**18 // supply
Updates

Lead Judging Commences

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

[invalid] finding-division-by-zero

Note that `total_supply` and `profit_unlocking_rate` is initially set to 1 and 0 respectively when the `ScrvusdOracleV2.vy` is deployed 1. `total_supply` and `profit_unlocking_rate` is part of the price param updates within `update_price`, which must have gone through verification via the OOS `StateProofVerifier` contract, so there is no evidence that a 0 supply is allowed either via a 0 supply update or an extremely high `profit_unlocking_rate`. 2. Since price is retrieved via values retrived from the V3Vault, if there is no supply, there is arguably no price to be posted. As such, reverting is arguably the correct choice since a 0 price value is not expected from scrvUSD, which is a stable coin.

Support

FAQs

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