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

No Oracle Return Validation in ScrvusdVerifierV1

Summary

In the ScrvusdVerifierV1 contract related to the lack of validation for return values from Oracle update functions. The contract fails to perform any validation on the price values returned by the oracle, which could lead to the propagation of incorrect, manipulated, or extreme values throughout the system. This vulnerability creates a potentially serious risk to the integrity and security of the price feed mechanism that could impact the entire ecosystem relying on this data.

Vulnerability Details

The vulnerability is present in both the verifyScrvusdByBlockHash and verifyScrvusdByStateRoot functions, which ultimately call the SCRVUSD Oracle's update_price function through the _updatePrice function:

function verifyScrvusdByBlockHash(
bytes memory _block_header_rlp,
bytes memory _proof_rlp
) external returns (uint256) {
Verifier.BlockHeader memory block_header = Verifier.parseBlockHeader(_block_header_rlp);
require(block_header.hash != bytes32(0), "Invalid blockhash");
require(
block_header.hash == IBlockHashOracle(BLOCK_HASH_ORACLE).get_block_hash(block_header.number),
"Blockhash mismatch"
);
uint256[PARAM_CNT] memory params = _extractParametersFromProof(block_header.stateRootHash, _proof_rlp);
return _updatePrice(params, block_header.timestamp, block_header.number);
}
function verifyScrvusdByStateRoot(
uint256 _block_number,
bytes memory _proof_rlp
) external returns (uint256) {
bytes32 state_root = IBlockHashOracle(BLOCK_HASH_ORACLE).get_state_root(_block_number);
uint256[PARAM_CNT] memory params = _extractParametersFromProof(state_root, _proof_rlp);
return _updatePrice(params, params[5], _block_number);
}

The main issues are:

  1. Both functions directly return the value from _updatePrice without any validation.

  2. There are no checks to ensure the returned price is within reasonable bounds.

  3. There is no verification that the oracle update was successful, rather than returning a default or error value.

  4. The code lacks any circuit breakers or sanity checks for extreme price changes.

From the available code, it appears that the _updatePrice function likely calls the oracle's update_price method defined in the IScrvusdOracle interface:

interface IScrvusdOracle {
function update_price(
uint256[PARAM_CNT] memory _parameters,
uint256 _ts,
uint256 _block_number
) external returns (uint256);
}

Without proper validation, any value returned by this function is blindly accepted and propagated through the system.

Impact

The impact of this vulnerability is:

  1. Price Manipulation: Incorrect or manipulated price data could be accepted and propagated throughout the system, potentially leading to financial losses.

  2. Flash Loan Attacks: Without validation, attackers might exploit flash loans to manipulate underlying parameters that affect the price calculation.

  3. Cascading Failures: Other protocols relying on this price feed could make incorrect financial decisions based on invalid data.

  4. Economic Exploits: Extreme price values could be used to drain liquidity pools or manipulate collateralization ratios in lending protocols.

  5. System Instability: Unexpected price movements could trigger liquidations or other automated actions that destabilize the ecosystem.

Likelihood Assessment

The likelihood of this vulnerability causing issues is assessed as MEDIUM based on:

  1. Systemic Pattern: The lack of validation is consistent across multiple functions, indicating a systemic design issue.

  2. Critical Functionality: Price updates are fundamental to DeFi operations, making this a high-value target for attackers.

  3. Compound Risk: This vulnerability exacerbates other identified issues in the codebase, such as timestamp surrogate problems and unverified slot existence.

  4. Market Conditions: Even without malicious intent, extreme market volatility could lead to price values that should be validated or smoothed.

  5. Precedent: Similar vulnerabilities have been exploited in other DeFi protocols, resulting in significant financial losses.

The chances of exploitation are significant in a production environment, especially considering the financial incentives for attackers and the critical nature of price data in DeFi ecosystems.

Tools Used

  • Manual code review

  • Static analysis

  • Contextual analysis of the oracle system architecture

  • Pattern recognition across the codebase

Recommendations

  1. Implement Bounds Checking: Add reasonable upper and lower bounds for price values:

function _updatePrice(uint256[PARAM_CNT] memory params, uint256 timestamp, uint256 blockNumber) internal returns (uint256) {
uint256 newPrice = IScrvusdOracle(SCRVUSD_ORACLE).update_price(params, timestamp, blockNumber);
// Add validation
require(newPrice > MIN_ACCEPTABLE_PRICE, "Price too low");
require(newPrice < MAX_ACCEPTABLE_PRICE, "Price too high");
return newPrice;
}
  1. Add Rate-of-Change Limits: Implement checks for maximum allowed price changes between updates:

uint256 previousPrice = getLastRecordedPrice();
uint256 maxChange = previousPrice * MAX_PRICE_CHANGE_PERCENTAGE / 100;
require(
newPrice >= previousPrice - maxChange &&
newPrice <= previousPrice + maxChange,
"Price change exceeds maximum allowed"
);
  1. Implement Circuit Breakers: Add mechanisms to pause price updates during extreme conditions:

if (isPriceExtremelyVolatile(newPrice, previousPrice)) {
emit PriceUpdatePaused(newPrice, previousPrice);
requireAdminConfirmation();
// Only proceed after admin confirmation
}
  1. Return Status Codes: Modify the oracle interface to return status codes alongside prices:

interface IScrvusdOracle {
function update_price(
uint256[PARAM_CNT] memory _parameters,
uint256 _ts,
uint256 _block_number
) external returns (uint256 price, bool success);
}
  1. Implement Time-Weighted Average Prices (TWAP): Use time-weighted averages to smooth price updates and reduce the impact of short-term manipulations.

  2. Add Comprehensive Logging: Implement detailed event logging for price updates, including all input parameters and validation results.

By implementing these recommendations, particularly the first two, the contract can significantly reduce the risk of accepting and propagating invalid price data, thereby enhancing the security and reliability of the entire system.

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.