In _extractParametersFromProof()
, the contract does not properly verify that the extracted slot values correspond to the expected storage slots in scrvUSD
. The function assumes that PARAM_SLOTS[i]
matches the proof order, but a malicious attacker could reorder the proof elements, leading to incorrect parameter extraction.
The attacker crafts a malicious proof with manipulated slot order.
_extractParametersFromProof()
iterates over proofs[i].toList()
without checking if PARAM_SLOTS[i]
actually corresponds to the extracted slot.
The attacker could inject arbitrary values into sensitive parameters like total_debt
, balanceOf(self)
, or profit_unlocking_rate
.
The manipulated values are then sent to IScrvusdOracle.update_price()
, leading to incorrect price updates and potential financial loss.
** **
Enforce Slot Verification
Modify _extractParametersFromProof()
to explicitly check the extracted slot key before assigning the value:
function _extractParametersFromProof( bytes32 stateRoot, bytes memory proofRlp ) internal view returns (uint256[PARAM_CNT] memory)
{
RLPReader.RLPItem[] memory proofs = proofRlp.toRlpItem().toList();
require(proofs.length == PROOF_CNT, "Invalid number of proofs");
// Extract account proof Verifier.Account memory account = Verifier.extractAccountFromProof( SCRVUSD_HASH, stateRoot, proofs[0].toList() );
require(account.exists, "scrvUSD account does not exist");
// Extract slot values securely uint256[PARAM_CNT] memory params;
for (uint256 i = 1; i < PROOF_CNT; i++) { bytes32 expectedSlotKey = keccak256(abi.encode(PARAM_SLOTS[i]));
// Correct slot key Verifier.SlotValue memory slot = Verifier.extractSlotValueFromProof( expectedSlotKey, account.storageRoot, proofs[i].toList() ); // **CRITICAL FIX**: Ensure slot.key matches expected storage slot require(slot.key == expectedSlotKey, "Storage slot mismatch"); params[i - 1] = slot.value;
} return params;
}
- 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.