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 5 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
5 months ago
0xnevi Lead Judge
5 months ago
0xnevi Lead Judge 4 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.