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

Division by Zero in Price Calculation Can Occur Due to Unchecked Total Supply

Summary

ScrvusdOracleV2::_raw_price function performs a division operation, total_assets * 10**18 // total_supply, which reverts if total_supply becomes zero. This can occur if the update_price function sets total_supply to 0 without validation, as there is no check to ensure _parameters[2] > 0

Vulnerability Details

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

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

Root Cause: The update_price function allows total_supply (_parameters[2]) to be set to 0 without validation. In _raw_price, the price calculation self._total_assets(parameters) * 10**18 // self._total_supply(parameters, ts) uses integer division (//), which reverts on division by zero. If total_supply is 0 and _unlocked_shares does not offset it sufficiently, _total_supply becomes 0, triggering the revert.

This occurs when update_price sets total_supply = 0 (via _parameters[2]) and _unlocked_shares returns a value that doesn’t exceed it (e.g., 0 when full_profit_unlock_date <= ts).

Impact

  • Revert in update_price: If total_supply = 0 and _unlocked_shares = 0, the call to _raw_price within update_price reverts, preventing price updates.

  • Post-update, price functions (price_v0, price_v1, price_v2) relying on _raw_price revert, breaking oracle availability.

Tools Used

Manual

Recommendations

  • Prevent total_supply = 0

@external
def update_price(
_parameters: uint256[ALL_PARAM_CNT], _ts: uint256, _block_number: uint256
) -> uint256:
access_control._check_role(PRICE_PARAMETERS_VERIFIER, msg.sender)
assert self.last_block_number <= _block_number, "Outdated"
+ assert _parameters[2] > 0, "Total supply must be positive"
self.last_block_number = _block_number
# ...
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.