DeFiLayer 1Layer 2
14,723 OP
View results
Submission Details
Severity: low
Invalid

Hardcoded Storage Slot for profit_max_unlock_time in VerifierV2

Summary

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.

Vulnerability Details

  • 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.

https://github.com/CodeHawks-Contests/2025-03-curve/blob/198820f0c30d5080f75073243677ff716429dbfd/contracts/scrvusd/verifiers/ScrvusdVerifierV2.sol#L19

Impact

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.

Tools Used

Recommendations

To mitigate this vulnerability, consider the following:

  1. 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.

  2. 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.

Updates

Lead Judging Commences

0xnevi Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope
Assigned finding tags:

[invalid] finding-upgradeable-verifier-contracts

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.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.