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

The ScrvusdVerifierV1 contract lacks validation for the critical parameter last_profit_update (params[5]), directly passing a potentially invalid value (0) to the Oracle.

Summary

In the ScrvusdVerifierV1 contract’s verifyScrvusdByStateRoot function, the last_profit_update (params[5]) is used as the timestamp parameter for updating the price in the Oracle. However, the contract does not check whether params[5] is 0 or an invalid value, and passes it directly to the Oracle.

Vulnerability Details

In the current cross-chain scrvUSD oracle implementation, the ScrvusdVerifierV1 contract extracts key parameters from state proofs and passes them to the update_price function of the ScrvusdOracle contract. However, two severe vulnerabilities exist here:

  1. Missing Validation of the Parameter last_profit_update (i.e., params[5]) in the Verifier contract:

    • As indicated by contract comments, the storage slot may not exist and defaults to zero.

    • If this parameter is zero, the Verifier incorrectly uses 0 as a valid timestamp for updating the oracle price.

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);
// ⚠️ params[5] is used without validation:
return _updatePrice(params, params[5], _block_number);
}

2.Lack of Validation for the External Timestamp (_ts) in the Oracle contract’s** update_price function:

  • The function directly assigns the externally provided _ts to self.price_params_ts without any validation.

  • There's no check whether _ts is an abnormal timestamp (far past or future).

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
"""
.........
self.price_params_ts = _ts #<-@ here,
# ⚠️ There's no check whether `_ts` is an abnormal timestamp(i.e zero)
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

These two issues, when combined, may allow an verifier providing a abnormal timestamps to update price.(As indicated by contract comments, the storage slot may not exist and defaults to zero.)


Impact

  1. The Oracle contract accepts zero as valid without validation, significantly distorting internal computations.It severely jeopardizes the accuracy of the oracle's pricing.

Tools Used

N/A

Recommendations

Add strict timestamp validation in the update_price function.

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.