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

Incorrect storage slot calculation corrupts key protocol values

Summary

The contract double-hashes storage slot keys causing it to read garbage data for critical scrvUSD vault parameters (e.g., total_debt, balanceOf). This corrupts the oracle’s price calculation.

Vulnerability Details

The contract stores key protocol values in specific storage slots:

uint256[PROOF_CNT] internal PARAM_SLOTS = [
uint256(0), // filler for account proof
uint256(21), // total_debt
uint256(22), // total_idle
uint256(20), // totalSupply
uint256(38), // full_profit_unlock_date
uint256(39), // profit_unlocking_rate
uint256(40), // last_profit_update
uint256(keccak256(abi.encode(18, SCRVUSD))) // balanceOf(self)
];

However, when fetching data in _extractParametersFromProof() , the contract rehashes the slot values altering the expected storage keys:

// Extract slot values
uint256[PARAM_CNT] memory params;
for (uint256 i = 1; i < PROOF_CNT; i++) {
Verifier.SlotValue memory slot = Verifier.extractSlotValueFromProof(
keccak256(abi.encode(PARAM_SLOTS[i])), // Incorrect double-hashing
account.storageRoot,
proofs[i].toList()
);
// Slots might not exist, but typically we just read them.
params[i - 1] = slot.value;
}

Static Slots (e.g., total_debt at slot 21): The slot should be directly referenced as 21 but instead, keccak256(abi.encode(21)) is used pointing to an invalid storage location.

Dynamic Slots (e.g., balanceOf(self)): The correct storage key should be keccak256(abi.encode(18, SCRVUSD)), but the contract hashes it again resulting in an incorrect key.

Impact

The contract reads garbage values instead of actual protocol parameters.

Tools Used

Manual code review

Recommendations

Updates

Lead Judging Commences

0xnevi Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

[invalid] finding-ScrvusdVerifierV1-incorrect-storage-slot-balanceOf-compute

- Per sponsor comments, verified slot is vyper, solidity contract only verifies it. - Vyper computes storage slots different from solidity as seen [here](https://ethereum.stackexchange.com/questions/149311/storage-collision-in-vyper-hashmap)

Support

FAQs

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