The scrvUSD
oracle system contains a critical vulnerability in the calculation logic. If profit_max_unlock_time
is set to zero, it would cause a division by zero error in the _obtain_price_params
function when calculating number_of_periods
. This occurs in the operation:
`number_of_periods = (parameters_ts - params.last_profit_update) // period`
Since period
would be zero, this division operation would revert, causing a permanent denial of service for all oracle price calculations. This would effectively paralyze the entire oracle system, potentially affecting any dependent financial operations.
The vulnerability has high severity due to:
System-wide impact on core oracle functionality
Potential financial implications for dependent contracts
Persistent failure state requiring contract updates
Complete denial of service for price queries
Adding a simple validation check to ensure profit_max_unlock_time
is always greater than zero would effectively mitigate this vulnerability.
The scrvUSD
oracle implementation has a critical vulnerability that can cause a division by zero error. This occurs in the _obtain_price_params
function where the code calculates the number of periods using the following division operation:
`number_of_periods: uint256 = min( (parameters_ts - params.last_profit_update) // period, self.max_v2_duration, )`
In this calculation, period
is set to the value of self.profit_max_unlock_time
. If profit_max_unlock_time
is set to zero (which is possible through the update_profit_max_unlock_time
function), this would cause a division by zero error, reverting all transactions that execute this code path.
The vulnerability stems from the absence of validation checks in the update_profit_max_unlock_time
function:
`@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 self.last_block_number <= _block_number, "Outdated" self.last_block_number = _block_number prev_value: uint256 = self.profit_max_unlock_time self.profit_max_unlock_time = _profit_max_unlock_time return prev_value != _profit_max_unlock_time`
This function accepts any value for _profit_max_unlock_time
, including zero, without performing boundary validation.
The impact of this vulnerability is severe for several reasons:
Complete Oracle Failure:
The _obtain_price_params
function is called by all price calculation methods (price_v1
, price_v2
, raw_price
).
A zero period would make all these functions revert, causing a total denial of service for the oracle.
Permanent System Breakdown:
Once profit_max_unlock_time
is set to zero, the oracle becomes unusable until a contract upgrade or migration is performed.
This would require governance intervention and could lead to significant downtime.
Financial Implications:
As an oracle for scrvUSD
share price, this component likely serves critical financial infrastructure.
Any systems relying on this oracle for pricing or valuation would be affected.
This could potentially freeze assets or break dependent protocols.
Difficult Recovery:
Recovering from this state would require a privileged transaction to reset the value.
If the issue is discovered during an attack, there could be a race condition between attackers and defenders.
An address with the UNLOCK_TIME_VERIFIER
role calls update_profit_max_unlock_time(0, current_block_number)
.
The profit_max_unlock_time
is set to 0.
Any subsequent call to price_v1
, price_v2
, or raw_price
that triggers the _obtain_price_params
function will revert due to division by zero.
manual review
`
`
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.