The last_block_number
state variable in the scrvUSD oracle contract is not initialized in the constructor (__init__
). This omission results in its default value being 0
. The update_price
function compares the provided _block_number
argument against last_block_number
to prevent outdated price updates. However, since last_block_number
starts at zero, the first call to update_price
will accept any _block_number
greater than or equal to zero. This creates an opportunity for stale or outdated _block_number
values to be used during the first update, which may lead to inconsistent or inaccurate price data.
The last_block_number
variable is not explicitly initialized in the constructor (__init__
). By default, it assumes a value of zero.
During the first call to update_price
, last_block_number
will always be 0
. This assertion:
will pass for any _block_number
≥ 0, including stale or outdated values. This violates the intended logic of strictly enforcing monotonically increasing _block_number
values, potentially allowing an outdated _parameters
set to be accepted on the first call.
The update_price
function could accept outdated _block_number
values on its first invocation, causing the contract to log or store stale or incorrect price data. If incorrect price_params
are updated with an old block number, subsequent calculations relying on accurate and fresh parameters could lead to inaccurate oracle prices. This behavior undermines the oracle’s integrity and potentially exposes integrations (StableSwap pools and other systems depending on scrvUSD) to stale pricing, increasing the risk of manipulation or mispricing in dependent protocols.
Manual Review
Explicitly initialize last_block_number
in the constructor (__init__
) with the current block number at deployment to ensure that only updates with valid, fresh block numbers are allowed:
I believe low to be appropriate, although could hear arguments for informational. The next `_block_number` for each price/max unlock time update will always be greater than the default zero, so the assertion of `assert self.last_block_number <= _block_number, "Outdated"` will pass without issue, but for consistency could be updated during deployment. Arguably at deployment, an update that has been verified via the verifier has not occur yet, so there would likely be no issues here given after the first correct update it will work as intended. The first update for price/profit max unlock time will also unlikely be outdated based on block number, which can be presumed to be true given this are extracted and verified within the OOS `StateProofVerifier`.
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.