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

Missing Parameter Validation in Oracle Price Update Function

Summary

The update_price function in the ScrvusdOracleV2.vy contract accepts critical price parameters without performing any validation, allowing privileged users to set arbitrary values that could manipulate prices or cause denial of service.

Vulnerability Details

ScrvusdOracleV2.vy#L294-L330

The vulnerability exists in the update_price function:

@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],
)
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

The issue stems from the lack of validation of the _parameters array before storing the values in the contract state. While the function does include an access control check to ensure only authorized callers can update parameters, it doesn't:

  1. Validate that the parameters fall within reasonable bounds

  2. Check for logical consistency between related parameters (e.g., total_supply ≥ balance_of_self)

  3. Ensure that changes from previous values are within acceptable limits

  4. Verify that the provided timestamp (_ts) is reasonable

These parameters directly influence the price calculation through the _raw_price function and are used throughout the contract.

Impact

This vulnerability could lead to several serious consequences:

  1. Price Manipulation: An attacker with the PRICE_PARAMETERS_VERIFIER role could set parameters to manipulate the calculated price of scrvUSD, potentially impacting dependent protocols and users.

  2. Denial of Service: Certain combinations of parameters could cause computational errors or reverts in functions that use these parameters, making the oracle unusable.

  3. Economic Exploits: If integrated with other DeFi protocols, price manipulation could create arbitrage opportunities or allow exploitative trades.

  4. Breaking Logical Invariants: Setting inconsistent parameters could break expected relationships between values, causing unpredictable behavior throughout the contract.

The risk is elevated because there are no circuit breakers or bounds that would prevent extreme manipulation of these critical values.

Tools Used

  • Manual code review

  • Analysis of contract business logic

  • Review of function behaviors and dependencies

Recommendations

  1. Implement Parameter Validation:

    # Example validation checks
    assert _parameters[2] > 0, "Total supply must be positive" # total_supply
    assert _parameters[6] <= _parameters[2], "Balance cannot exceed total supply" # balance_of_self <= total_supply
    assert _parameters[3] >= block.timestamp, "Unlock date must be in the future" # full_profit_unlock_date
  2. Add Rate Limiting:

    # Check for reasonable changes from previous values
    assert abs(int256(_parameters[0]) - int256(self.price_params.total_debt)) <= MAX_DEBT_CHANGE, "Debt change too large"
  3. Implement Oracle Guards:

    # Verify the resulting price is within reasonable bounds
    new_price: uint256 = self._calculate_price_with_parameters(_parameters)
    assert new_price >= MIN_ACCEPTABLE_PRICE and new_price <= MAX_ACCEPTABLE_PRICE, "Price outside acceptable range"
  4. Add Time-Based Validation:

    # Ensure timestamp is reasonable
    assert _ts >= block.timestamp - MAX_PAST_TIMESTAMP and _ts <= block.timestamp, "Invalid timestamp"
  5. Consider a Multi-Oracle Setup:
    Implement a system where multiple independent oracles must agree on parameter changes that exceed certain thresholds.

  6. Add Emergency Functions:
    Implement functions that allow admins to reset parameters to safe values in case of manipulation.

By implementing these recommendations, the contract would be better protected against parameter manipulation while maintaining its core functionality.

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

Support

FAQs

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