The Curve scrvUSD
Savings Vault relies on oracle updates to propagate accurate price and rate information across chains. If an incorrect blockhash is provided in the update_price()
function and not corrected in a timely manner, the system may process invalid pricing data. Simultaneously, the update_profit_max_unlock_time()
function can progress the system’s block_number
even while the erroneous data persists. This may allow attackers to exploit mispriced assets in Curve’s stableswap-ng pools, leading to potential cross-chain arbitrage opportunities and liquidity drains from affected pools. Although smoothing mechanisms and APR caps offer mitigation, delayed correction of oracle data still exposes the protocol and liquidity providers to significant financial risk.
The vulnerability stems from oracle data updates dependent on external blockhash verification, which can occasionally be incorrect or delayed as mention in the docs that;
The Curve oracle architecture allows both update_price()
and update_profit_max_unlock_time()
to modify the block_number
, but there is no enforced synchronization ensuring that an incorrect oracle price is corrected before progressing the system state.
update_price()
: Updates scrvUSD price based on a provided blockhash and other parameters.
update_profit_max_unlock_time()
: Updates the profit unlock timeline and advances block_number
, even when the previous price update was erroneous.
If an incorrect blockhash leads to the propagation of an inaccurate price or rate block_number
advances regardless of the incorrect data. Smoothing mechanisms and rate caps limit short-term damage but cannot prevent systematic exploitation of incorrect data.
Until the incorrect blockhash and price are corrected, the following conditions are present; Mispriced scrvUSD in stableswap-ng pools Profit unlock mechanisms operating on inaccurate rate assumptions.
Mispriced scrvUSD on L2 chains (e.g., Optimism, Arbitrum) leads to arbitrage opportunities. Attackers can buy undervalued scrvUSD on L2, bridge it back to Ethereum where it has higher value, and profit from the spread Conversely, if scrvUSD is overpriced, attackers can sell into Curve L2 pools, draining assets like USDC or FRAX.
Curve’s stableswap-ng pools rely on the oracle for price alignment. A faulty price that isn’t corrected promptly results in imbalanced pools, making them susceptible to being drained on one side.
Manual Review
Implement strict validation to prevent either update_profit_max_unlock_time()
or update_price()
from progressing the block_number
unless the most recent oracle price update is verified as accurate.
- 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
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.