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

Input Validation Deficiency: Unchecked _block_number in verifyPeriodByStateRoot

Summary

The verifyPeriodByStateRoot function does not validate the _block_number parameter, allowing invalid (e.g., 0) or future block numbers to be passed to the IBlockHashOracle. This could lead to reverts or unexpected behavior, disrupting the update process.

Vulnerability Details

Description: The verifyPeriodByStateRoot function accepts _block_number without any validation:

function verifyPeriodByStateRoot(uint256 _block_number, bytes memory _proof_rlp) external returns (bool) {
bytes32 state_root = IBlockHashOracle(ScrvusdVerifierV1.BLOCK_HASH_ORACLE).get_state_root(_block_number);
// Existing logic
}

A value of 0 is invalid for Ethereum block numbers (block 0 is the genesis block, but state roots are typically not queried for it in this context).
A future block number (greater than block.number) could cause the get_state_root call to fail or return unexpected data, depending on the IBlockHashOracle ## implementation.

  • Root Cause: Absence of bounds checking for the _block_number parameter.

Impact

  • Severity:
    Medium

  • Description:
    An invalid _block_number (e.g., 0) could cause the get_state_root call to revert, preventing updates and leading to a temporary DoS condition. A future block number could result in undefined behavior (e.g., reverts or incorrect state roots), potentially allowing inconsistent updates if the IBlockHashOracle returns a default value. Downstream systems may reject updates, but operational delays are possible.

  • Likelihood:
    Low, as most callers are expected to provide valid block numbers, but the risk increases with public access and lack of validation.

Tools Used

  • Manual Code Review:
    Checked for input validation in verifyPeriodByStateRoot across multiple passes.

Recommendations

  • Block Number Validation: Add bounds checking for _block_number in verifyPeriodByStateRoot:

function verifyPeriodByStateRoot(uint256 _block_number, bytes memory _proof_rlp) external returns (bool) {
require(_block_number <= block.number, "Future block not allowed");
require(_block_number > 0, "Invalid block number");
bytes32 state_root = IBlockHashOracle(ScrvusdVerifierV1.BLOCK_HASH_ORACLE).get_state_root(_block_number);
// Existing logic
}
Updates

Lead Judging Commences

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

[invalid] finding-block-number-no-input-check

- Anything related to the output by the `BLOCK_HASH_ORACLE` is OOS per \[docs here]\(<https://github.com/CodeHawks-Contests/2025-03-curve?tab=readme-ov-file#blockhash-oracle>). - The PoC utilizes a mock `BLOCK_HASH_ORACLE`which is not representative of the one used by the protocol - Even when block hash returned is incorrect, the assumption is already explicitly made known in the docs, and the contract allows a subsequent update within the same block to update and correct prices - All state roots and proofs must be verified by the OOS `StateProofVerifier` inherited as `Verifier`, so there is no proof that manipulating block timestamp/block number/inputs can affect a price update - There seems to be a lot of confusion on the block hash check. The block hash check is a unique identifier of a block and has nothing to do with the state root. All value verifications is performed by the OOS Verifier contract as mentioned above

Support

FAQs

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