The ScrvusdVerifierV1 contract’s _extractParametersFromProof function silently accepts zero values for missing storage slot proofs, skewing vault parameters like total_supply or total_debt. This can lead to inaccurate scrvUSD price updates, enabling arbitrage or pool imbalances without detection.
The vulnerable code is in _extractParametersFromProof:
solidity
Silent Zero Values:
Verifier.extractSlotValueFromProof returns slot.value = 0 if the slot isn’t proven, without flagging slot.exists.
No validation ensures all parameters are non-zero or present.
Contrast: ScrvusdVerifierV2 checks slot.exists, showing intent to avoid this.
PoC
Silent Parameter Skew in ScrvusdVerifierV1
Objective
Skew scrvUSD pricing by submitting a partial proof that zeros out total_supply, underpricing the asset.
Prerequisites
Deployed ScrvusdVerifierV1 and scrvUSD oracle.
Ability to craft RLP-encoded proofs (e.g., via off-chain script or test tooling).
Control of proof submission (assume verifier role or test environment).
Exploit Scenario
An attacker submits a proof missing the total_supply slot, causing it to default to 0, which misprices scrvUSD and enables arbitrage.
Proof of Concept Steps
Setup: Deploy ScrvusdVerifierV1 linked to the oracle.
Craft Malicious Proof:
Use an off-chain tool (e.g., Python with rlp library) to create an RLP proof with only 7 items (instead of 8), omitting the total_supply slot (slot 20).
Example pseudo-code:
python
Exploit:
Call verifyScrvusdByBlockHash with a valid block header and the malformed proof_rlp.
total_supply defaults to 0, triggering a division-by-zero revert or, if patched, a low price.
Result: Oracle updates with skewed parameters, e.g., price drops to near-zero, allowing arbitrage in stableswap-ng pools.
Outcome
Demonstrates how silent skewing misprices scrvUSD, exploitable until corrected.
Mispricing: Zeroed parameters (e.g., total_supply = 0) distort price calculations, potentially triggering the division-by- zero issue or underpricing scrvUSD.
Arbitrage: Inaccurate prices in stableswap-ng pools allow profit extraction at liquidity providers’ expense.
Stealth Exploit: Silent failure makes this hard to detect without monitoring.
Manual Review
Require slot existence in _extractParametersFromProof:
solidity
- Looking at the OOS `StateProofVerifier` and `MerklePatriciaProofVerifier` contract that extracts the slot, the `exists` flag will be flagged as true as long as a non-zero length value is returned as seen [here](https://github.com/curvefi/curve-xdao/blob/3ff77bd2ccc9c88d50ee42d2a746fc7648c7ff2c/contracts/libs/StateProofVerifier.sol#L133C13-L136). From the `MerklePatriciaProofVerifier.extractProofValue`, the minimum length returned will be 1 as represenetd by `bytes(0)`. So this seems to be purely a sanity check that might not even be required. - A slot with zero values is only allowed when the proof provided by the prover correctly proofs that such values are included within the Merkle-Patricia-Tree. The values fetched from mainnet from the V3Vault stored in the merkle trie is likely checked before hand and aggregated into the MerkleTree.
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.