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

Unchecked External Calls Risk Silent Failures Leading to Incorrect State

Summary

The _updatePrice and verifyPeriodByBlockHash functions in ScrvusdVerifierV1 and ScrvusdVerifierV2 make external calls to oracle contracts without verifying success. If these calls fail (e.g., due to invalid parameters or a compromised oracle), the verifiers proceed as if the updates succeeded, resulting in stale or corrupted price data. This could allow attackers to manipulate dependent systems like stableswap pools.

Vulnerability Details

How Unchecked Calls Work:

  1. External Call: The verifier calls IScrvusdOracle.update_price(...) or IScrvusdOracleV2.update_profit_max_unlock_time(...).

  2. Silent Failure: If the oracle function reverts or returns false, the verifier ignores the failure and continues execution.

  3. Invalid State: The verifier assumes the update succeeded, leaving the system with outdated or incorrect parameters.

Impact

  • Incorrect Prices: Stale or invalid parameters produce wrong prices, enabling arbitrage attacks or fund drainage.

  • System Instability: Dependent protocols (e.g., stableswap-ng pools) operate on corrupted data, risking collapse.

Tools Used

Recommendations

Use Low-Level Calls with Explicit Success Checks:

Replace direct interface calls with low-level .call() and validate the result:

// In ScrvusdVerifierV1.sol
function _updatePrice(...) internal {
(bool success, ) = address(SCRVUSD_ORACLE).call(
abi.encodeWithSelector(
IScrvusdOracle.update_price.selector,
params,
ts,
number
)
);
require(success, "Oracle update failed");
}
// In ScrvusdVerifierV2.sol
function verifyPeriodByBlockHash(...) external {
(bool success, ) = address(SCRVUSD_ORACLE).call(
abi.encodeWithSelector(
IScrvusdOracleV2.update_profit_max_unlock_time.selector,
period,
block_header.number
)
);
require(success, "Unlock time update failed");
}

Why This Fixes the Issue:
Explicit Failure Handling: The require statement ensures the transaction reverts if the external call fails.

State Consistency: Invalid updates are rejected, preventing corrupted data propagation.

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.