The ScrvusdVerifierV1 and ScrvusdVerifierV2 contracts are designed to verify and update the scrvUSD price and profit_max_unlock_time parameters using state proofs. However, a vulnerability exists due to the lack of strict validation on the block_number parameter in the update_price and update_profit_max_unlock_time functions. This allows an attacker to front-run legitimate calls by submitting a newer block_number through ScrvusdVerifierV2, causing subsequent legitimate calls to fail. This issue can disrupt the normal operation of the system and potentially be exploited for malicious purposes.
In ScrvusdVerifierV1 , anyone can call verifyScrvusdByBlockHash and verifyScrvusdByStateRoot :
These two functions will call update_price :
In ScrvusdOracle , the update_price function will check the last_block_number :
In ScrvusdVerifierV2 , anyone can call verifyPeriodByBlockHash and verifyPeriodByStateRoot :
which will call update_profit_max_unlock_time :
In ScrvusdOracle , the update_profit_max_unlock_time function will check the same last_block_number :
The vulnerability arises because both update_price and update_profit_max_unlock_time functions validate the block_number against the same last_block_number. If a user submits a transaction with an older block_number, an attacker can monitor the transaction and front-run it by submitting a newer block_number through ScrvusdVerifierV2. This causes the legitimate transaction to fail due to the block_number being outdated.
Attack Scenario
A user calls ScrvusdVerifierV1's verifyScrvusdByBlockHash or verifyScrvusdByStateRoot function, submitting an older block_number.
An attacker observes the transaction and quickly calls ScrvusdVerifierV2's verifyPeriodByBlockHash or verifyPeriodByStateRoot function, submitting a newer block_number.
The attacker's transaction is executed first, updating the last_block_number to the newer value.
The user's transaction is executed afterward but fails because the submitted block_number is now considered outdated.
Legitimate transactions may fail, preventing the timely update of scrvUSD prices or profit_max_unlock_time.
Attackers can exploit this vulnerability to disrupt the system's normal operation or manipulate parameters for their benefit.
The system's reliability and trustworthiness may be compromised.
The impact is Medium, the likelihood is Medium, so the severity is Medium.
Manual Review
Do not use the same last_block_number for different function.
- 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
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.