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

[H-01] Arbitrary timestamp can be provided to manipulate the price of the `scrvUSD` token

Summary

Arbitrary timestamp can be provided to manipulate the price of the scrvUSD token

Vulnerability Details

In the contract ScrvusdOracleV2.vy:update_price():324 there's no validation for the parameter _ts which is the timestamp. A user may able to pass a timestamp in future which will update the value of self.price_params_ts variable which will cause the _price_v0(), _price_v1(), _price_v2() to break as they depend on this.

@external
def update_price(
_parameters: uint256[ALL_PARAM_CNT], _ts: uint256, _block_number: uint256
) -> uint256:
"""
@notice Update price using `_parameters`
@param _parameters Parameters of Yearn Vault to calculate scrvUSD price
@param _ts Timestamp at which these parameters are true
@param _block_number Block number of parameters to linearize updates
@return Absolute relative price change of final price with 10^18 precision
"""
access_control._check_role(PRICE_PARAMETERS_VERIFIER, msg.sender)
# Allowing same block updates for fixing bad blockhash provided (if possible)
assert self.last_block_number <= _block_number, "Outdated"
self.last_block_number = _block_number
self.last_prices = [self._price_v0(), self._price_v1(), self._price_v2()]
self.last_update = block.timestamp
ts: uint256 = self.price_params_ts
current_price: uint256 = self._raw_price(ts, ts)
self.price_params = PriceParams(
total_debt=_parameters[0],
total_idle=_parameters[1],
total_supply=_parameters[2],
full_profit_unlock_date=_parameters[3],
profit_unlocking_rate=_parameters[4],
last_profit_update=_parameters[5],
balance_of_self=_parameters[6],
)
#@> No validation of the _ts prarameter before setting the value
self.price_params_ts = _ts
new_price: uint256 = self._raw_price(_ts, _ts)
log PriceUpdate(new_price, _ts, _block_number)
if new_price > current_price:
return (new_price - current_price) * 10**18 // current_price
return (current_price - new_price) * 10**18 // current_price

Impact

The price of the scrvUSDtoken will be incorrect.

Tools Used

Manual review

Recommendations

@external
def update_price(
_parameters: uint256[ALL_PARAM_CNT], _ts: uint256, _block_number: uint256
) -> uint256:
"""
@notice Update price using `_parameters`
@param _parameters Parameters of Yearn Vault to calculate scrvUSD price
@param _ts Timestamp at which these parameters are true
@param _block_number Block number of parameters to linearize updates
@return Absolute relative price change of final price with 10^18 precision
"""
access_control._check_role(PRICE_PARAMETERS_VERIFIER, msg.sender)
# Allowing same block updates for fixing bad blockhash provided (if possible)
assert self.last_block_number <= _block_number, "Outdated"
self.last_block_number = _block_number
self.last_prices = [self._price_v0(), self._price_v1(), self._price_v2()]
self.last_update = block.timestamp
ts: uint256 = self.price_params_ts
current_price: uint256 = self._raw_price(ts, ts)
self.price_params = PriceParams(
total_debt=_parameters[0],
total_idle=_parameters[1],
total_supply=_parameters[2],
full_profit_unlock_date=_parameters[3],
profit_unlocking_rate=_parameters[4],
last_profit_update=_parameters[5],
balance_of_self=_parameters[6],
)
++ # or similar relevant checks to ensure the value of the correct value
++ # of the srcvUSD token fetched
++ assert _ts <= block.timestamp, "Incorrect timestamp"
self.price_params_ts = _ts
new_price: uint256 = self._raw_price(_ts, _ts)
log PriceUpdate(new_price, _ts, _block_number)
if new_price > current_price:
return (new_price - current_price) * 10**18 // current_price
return (current_price - new_price) * 10**18 // current_price
Updates

Lead Judging Commences

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