In ScrvusdVerifierV2
, the _extractPeriodFromProof
function attempts to extract the value of the plain storage variable profit_max_unlock_time
(stored at slot 37) by computing its key as follows:
However, for a plain storage variable (i.e. one not in a mapping), the correct storage key in Ethereum’s state trie is simply the 32‑byte, left‑padded representation of the slot number:
—not the hash of its ABI-encoded value.
The use of keccak256(abi.encode(PERIOD_SLOT))
instead of bytes32(PERIOD_SLOT)
to compute the storage key for the profit_max_unlock_time
variable is a bug. This mistake causes the verifier to look for the wrong storage slot in the scrvUSD contract’s state, potentially leading to an incorrect or manipulable update to the oracle. Addressing this by using the proper direct padded representation of the slot number is critical for ensuring that the correct value is extracted from the Ethereum state proof.
Proof of Concept:
Standard Storage Key Computation:
For a plain variable stored at slot 37, the correct key in the account’s storage trie is:
This representation is simply the slot number padded to 32 bytes.
What the Code Does:
Instead, the contract computes the key as:
which produces a completely different 32‑byte value. This is appropriate for mapping entries (where keys are hashed with the mapping’s slot) but not for plain variables.
Consequences:
Failure to Locate the Storage Entry: A correct state proof (e.g., one obtained using eth_getProof
on a standard contract) would include the storage entry under the key bytes32(37)
. The verifier, however, will be looking for a key equal to keccak256(abi.encode(37))
. This mismatch means that the verifier will not retrieve the actual value for profit_max_unlock_time
.
Potential Exploitation: An attacker might craft a proof for the wrong key (the hashed key) to manipulate the period parameter passed to the oracle, leading to an unintended update of the profit unlock time.
Recommendation:
Change the key derivation for extracting the period value to use the proper padded representation:
See primary comments in issue #23
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.