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

Denial-of-Service (DoS) in _obtain_price_params due to Timestamp Mismatch

Summary

Contract: contracts/scrvusd/oracles/ScrvusdOracleV2.vy

Functions: _obtain_price_params, update_price

The update_price function in ScrvusdOracleV2.vy relies on a timestamp (parameters_ts) and a value (params.last_profit_update) obtained from a state proof of the scrvUSD vault on Ethereum mainnet. Due to delays in data synchronization and potential clock inaccuracies, it's possible for params.last_profit_update to be greater than parameters_ts.

Since the Vyper version is 0.4.0 which uses Solidity 0.8.18 compiler, if parameters_ts - params.last_profit_update results in underflow, the assertion parameters_ts >= params.last_profit_update will trigger a revert.
This results in a denial of service(DoS) because the price feed will not be updated.

Vulnerability Details

POC

Test Scenario:

  1. Deploy the Vyper contract.

  2. Call setup with _last_profit_update set to a future timestamp relative to the current block (e.g., block.timestamp + 7200 (2 hours)).

  3. Call update_price with parameters_ts = block.timestamp.

  4. Observe that the transaction reverts because the condition parameters_ts >= params.last_profit_update fails.

# Simplified PoC - Illustrates DoS
MAX_TIMESTAMP_DIFF: constant(uint256) = 3600 # Maximum timestamp difference (1 hour)
struct PriceParams:
last_profit_update: uint256
price_params: public(PriceParams)
@external
def setup(_last_profit_update: uint256):
self.price_params = PriceParams({last_profit_update: _last_profit_update})
@external
def update_price(parameters_ts: uint256):
# PoC
params: PriceParams = self.price_params
assert parameters_ts >= params.last_profit_update, "parameters_ts must be >= last_profit_update"
assert parameters_ts - params.last_profit_update <= MAX_TIMESTAMP_DIFF, "Timestamp difference too large"
# This call will trigger the subtraction, and therefore the potential DOS
# Pretend there is a `PriceUpdated` event

Impact

  • Denial-of-Service (DoS): The update_price function will revert if params.last_profit_update > parameters_ts, preventing the oracle from updating.

  • Stale Price Feed: An outdated price feed will cause inaccurate swaps in the stableswap pool, potential arbitrage by external parties, and loss of confidence in the system.

Tools Used

Manual review

Recommendations

Check and Adjust Timestamp:

Modify the update_price function to check if params.last_profit_update > parameters_ts before performing any calculations.

If params.last_profit_update is greater, adjust parameters_ts to be equal to params.last_profit_update to prevent the revert and ensure forward progress.

This makes the timestamp for this sidechain adjust to whatever the timestamp is on the mainchain oracle.

@external
def update_price(parameters_ts: uint256):
# PoC
params: PriceParams = self.price_params
if params.last_profit_update > parameters_ts:
parameters_ts = params.last_profit_update
assert parameters_ts - params.last_profit_update <= MAX_TIMESTAMP_DIFF, "Timestamp difference too large"
# This call will trigger the subtraction, and therefore the potential DOS
# Pretend there is a `PriceUpdated` event
Updates

Lead Judging Commences

0xnevi Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope
Assigned finding tags:

[invalid] finding-timestamp-underflow

This issues and duplicates are very similar to reasonings highlighted in issue #11. The timestamp variables are extracted and verified via the OOS `StateProofVerifier` contract inherited as `Verifier`. There is simply no concrete proof that the verifier allowed such an underflow to occur, representing stale price value updates.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.