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

Incorrect Storage Slot Calculation for balanceOf

Summary

In ScrvusdVerifierV1.sol in the PARAM_SLOTS array initialization, specifically in how the storage slot for balanceOf(self) is calculated: #L32-L40

uint256[PROOF_CNT] internal PARAM_SLOTS = [
uint256(0), // filler for account proof
// ...
uint256(keccak256(abi.encode(18, SCRVUSD))) // balanceOf(self)
];

The root cause is that the arguments to abi.encode() are in the wrong order.

Technical Details

In Solidity, for a mapping mapping(address => uint256) stored at slot p, the storage slot for a specific key k is calculated as

keccak256(abi.encode(k, p))

Where:

  • k is the mapping key (an address in this case)

  • p is the slot number of the mapping itself

For the balanceOf mapping at slot 18, the correct storage slot for balanceOf[SCRVUSD] should be:

keccak256(abi.encode(SCRVUSD, 18)) // correct

However, the code computes:

keccak256(abi.encode(18, SCRVUSD)) // incorrect

This reverses the arguments, computing an entirely different storage slot that doesn't correspond to any relevant data.

Vulnerability Details

In the code, they're computing keccak(abi.encode(18, SCRVUSD)), which would be h(18) followed by h(SCRVUSD), which is different. Therefore, the code is using the wrong slot for balanceOf, leading to incorrect data retrieval.

Impact

  1. The balance_of_self parameter is critical for calculating.

    • The total supply of assets via the _total_supply() function

    • The amount of unlocked shares via _unlocked_shares()

    • The price of scrvUSD via _raw_price()

  2. Since this oracle is intended for use in StableSwap pools, incorrect pricing would lead to.

    • Pools with incorrect asset ratios

    • Arbitrage opportunities that drain liquidity from pools

    • Financial losses for liquidity providers

  3. Since this oracle system is designed to operate across multiple chains, the incorrect pricing would propagate to all integrated chains and protocols.

This is problematic because the entire purpose of the oracle is to provide accurate pricing, and this bug directly undermines that core functionality.

Recommendations

swap the argument order in the abi.encode call

// Change from
uint256(keccak256(abi.encode(18, SCRVUSD)))
// To
uint256(keccak256(abi.encode(SCRVUSD, 18)))

This will ensure the correct storage slot is read, providing the actual balanceOf(self) value needed for accurate price calculations.

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.