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

Permanent DoS on ScrvusdOracleV2.vy::update_price due to div by zero (current_price value is zero)

Summary

ScrvusdOracleV2.vy::update_price is vulnerable to permanent denial of service if local function's current price variable is zero (return val from self.raw_price())

Vulnerability Details

The vulnerability occurs because ScrvusdOracleV2.vy::update_price defines the local variable current_price with raw_price() result to perform further calculations
Specifically is utilized to divide the subtraction between new_price and self._raw_price response.
However if current_price value is zero then an exception occurs and update_price functionality will be bricked forever:

@external
def update_price(
_parameters: uint256[ALL_PARAM_CNT], _ts: uint256, _block_number: uint256
) -> uint256:
# ...
current_price: uint256 = self._raw_price(ts, ts)
# ...
if new_price > current_price:
@> return (new_price - current_price) * 10**18 // current_price
@> return (current_price - new_price) * 10**18 // current_price

The following PoC shows the described scenario:
First verifier calls ScrvusdOracleV2.vy::update_price with zero price as new value,
Later verifier tries to change current price to a new value, but this is not possible due to division flaw described above:

Add the following code in tests/scrvusd/oracle/unitary/test_v2.py:

def test_update_price_div_by_zero_Mine(soracle, verifier, anne):
ts = boa.env.evm.patch.timestamp
price_1_5_parameters = [3, 0, 2, ts + 7 * 86400, 0, 0, 0]
price_0_5_parameters = [2, 0, 3, ts + 7 * 86400, 0, 0, 0]
price_0_x_parameters = [0, 0, 3, ts + 7 * 86400, 0, 0, 0]
with boa.env.prank(verifier):
# get current last_block_number
print("last_block_number => ",soracle.last_block_number())
# 1. Set price to zero
soracle.update_price(
price_0_x_parameters,
ts + 100, # timestamp
10, # block number
)
print("last_block_number => ",soracle.last_block_number())
# 2. Get current price
print("soracle.raw_price() ",soracle.raw_price())
# 3. Trying to set another price parameters reverts
with boa.reverts():
soracle.update_price(
price_0_x_parameters,
ts + 100, # timestamp
20, # block number
)

Exec test with:

pytest -s tests/scrvusd/oracle/unitary/test_v2.py

Note -s flag

The second call to update_price fails due to div by zero

Impact

Severity: This flaw leads to ScrvusdOracleV2.vy::update_price function to be permanently bricked

Tools Used

Manual Review

Recommendations

Implement a check to avoid division by zero

Updates

Lead Judging Commences

0xnevi Lead Judge 11 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

Appeal created

0xw3 Submitter
11 months ago
0xnevi Lead Judge
11 months ago
0xnevi Lead Judge 10 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.

Give us feedback!