The flow for update price for the scurvUSD oracle is this prover -> Verifier -> Oracle/UpdatePrice . To do this , a prover needs to provide a proof which is decoded into a price parameter and this parameter is used to update the price parameters on the oracle. Two major issues here
two key parameters (total_idle and total_supply) which must be non zero are not validated before updated on the oracle therefore errors like division by zero becomes possible.
Other parameter which are zero means prices given will be wrong
This is also solidified by the fact that in _extractPeriodFromProof in the ScrvusdVerifierV2.sol, the line of code here (https://github.com/CodeHawks-Contests/2025-03-curve/blob/main/contracts/scrvusd/verifiers/ScrvusdVerifierV2.sol#L74) ensures that the extracted period exists before calling the update_profit_max_unlock_time
The _extractParametersFromProof is a very important function in the verifier1.sol (https://github.com/CodeHawks-Contests/2025-03-curve/blob/main/contracts/scrvusd/verifiers/ScrvusdVerifierV1.sol#L83) I and its job is to call the verfier existing in curv-xdao to extract the value from a given proof. It uses the account proof to call Verifier.extractAccountFromProof to confirm the prover is from a valid account, and then uses the param proof to call Verifier.extractSlotValueFromProof to extract the param value.
The logic for extractSlotValueFromProof - https://github.com/curvefi/curve-xdao/blob/2fd7916bc58588e9b3bf3268ab27f1c0c77397f2/contracts/libs/StateProofVerifier.sol#L118C5-L139C6
This calls MerklePatriciaProofVerifier.extractProofValue and the logic for that is here https://github.com/curvefi/curve-xdao/blob/2fd7916bc58588e9b3bf3268ab27f1c0c77397f2/contracts/libs/MerklePatriciaProofVerifier.sol#L29
Here we can see that it is possible to get byte of zero based on multiple different conditions (one of which is an empty proof + rootHash ==
0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421) and if we do get this empty bytes then according to line 16 in function extractSlotValueFromProof if the byte is len 0 then return an empty initialized SlotValue meaning the value.value field is initailized to 0
Now from line 100 of verfirier1.sol showing _extractParametersFromProof we se that the value (even if it is 0 due to slot not existing as seen in comment is still saved) and returned
Now in verifyScrvusdByStateRoot when we call the update price after getting this param
The update price of the oracle (https://github.com/CodeHawks-Contests/2025-03-curve/blob/main/contracts/scrvusd/oracles/ScrvusdOracleV2.vy#L295) just updates the price params with the new one
This has a high impact on the oracle as the price values given at that point will be zero or throw error in many cases. For example here, the raw price will throw zero-division error if self.totalsupply returns zero (which it will if params.full_profit_unclok_date is 0) or raw price will be negative is params..total_supply is zero
Ensure there are validation checks to ensure that not all values are zero when the parameter is recvieved in updateprice
- 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.