The ScrvusdVerifierV2 contract hardcodes PERIOD_SLOT = 37 to read the profit_max_unlock_time value. Storage slots in Ethereum are determined by the order of variable declarations in the contract. If the scrvUSD contract’s storage layout changes (e.g., adding new variables before profit_max_unlock_time), the verifier will read incorrect data from the wrong slot.
Hardcoded Slot: ScrvusdVerifierV2.sol assumes profit_max_unlock_time is stored at slot 37.
Silent Failure: If the scrvUSD contract’s storage layout changes (upgrades, variable reordering), the verifier extracts garbage data without reverting.
Example:
Original scrvUSD: variable_A (slot 36), profit_max_unlock_time (slot 37).
Post-Upgrade: variable_A (slot 36), new_variable_B (slot 37), profit_max_unlock_time (slot 38).
VerifierV2 reads slot 37 (new_variable_B) instead of profit_max_unlock_time.
Arbitrage Losses: Traders could exploit price discrepancies, draining liquidity pools and causing losses for liquidity providers (LPs), potentially in the millions of dollars for large pools.
Depeg Events: If the oracle price deviates significantly, it could cause scrvUSD to lose its peg (e.g., deviating from $1), undermining trust in the stablecoin and triggering market panic, with cascading effects on related DeFi protocols.
To mitigate this vulnerability, consider the following:
Dynamic Slot Fetching:
Implement a configurable registry contract controlled by governance to store and update the correct storage slot for profit_max_unlock_time.
The verifier can query this registry to fetch the current slot dynamically, ensuring flexibility for contract upgrades.
Example: The registry could be a separate contract with a mapping of contract addresses to slot numbers, updated via governance proposals.
Sanity Checks:
Add validation checks on the extracted profit_max_unlock_time value to ensure it falls within expected bounds, such as:
require(period >= 1 days && period <= 1 years) to ensure the period is reasonable.
This can help detect if an incorrect value (e.g., 0 or a huge number) is read, triggering an error rather than silent failure.
Invalid, - srCRVUSD is a minimal proxy, meaning it can never by upgraded, see [here](https://www.cyfrin.io/blog/upgradeable-proxy-smart-contract-pattern#:~:text=Minimal%20proxies%20are%20distinct%20from,provide%20upgrade%20or%20authorization%20functionality.) and [here](https://www.rareskills.io/post/eip-1167-minimal-proxy-standard-with-initialization-clone-pattern) for more info. - Even if srcrvUSD is migrated in the future via a new minimal proxy contract deployment (which is highly unlikely), the verifier contracts can be migrated along with it via revoking the access-control within the `ScrvusdOracleV2.vy` and then granting access to a new oracle. This is also not within the scope of this contest.
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.