ScrvusdVerifierV1.sol
computes the account key hash (SCRVUSD_HASH
) for the scrvUSD
contract as keccak256(abi.encodePacked(SCRVUSD))
, passing it to Verifier.extractAccountFromProof()
to verify Ethereum state proofs. However, Ethereum’s state trie requires account keys to be hashed as keccak256(RLP.encode(address))
. This mismatch causes proof verification to fail consistently, as the provided key does not correspond to any valid trie path. As a result, the contract cannot extract scrvUSD
storage data, preventing oracle price updates to ScrvusdOracleV2
. This critical flaw renders the verifier non-functional, leading to stale or default pricing in downstream systems, with a High Severity impact due to its direct effect on protocol functionality.
The vulnerability arises in how ScrvusdVerifierV1
prepares the key (SCRVUSD_HASH
) to verify the scrvUSD
account state within Ethereum’s state trie:
Incorrect Hash Computation:
abi.encodePacked(SCRVUSD)
: Outputs the raw 20-byte address (e.g., 0x0655977FEb2f289A4aB78af67BAB0d17aAb84367).
keccak256(abi.encodePacked(SCRVUSD))
: Hashes the 20 bytes directly, producing a bytes32 value (e.g., keccak256(0x0655977FEb2f289A4aB78af67BAB0d17aAb84367)).
Usage in Proof Verification:
SCRVUSD_HASH
is passed as the key to extractAccountFromProof()
, which expects the trie key for SCRVUSD
’s account data.
Ethereum State Trie Expectation:
In Ethereum’s Patricia Merkle Trie, account keys are computed as keccak256(RLP.encode(address))
.
RLP encoding of a 20-byte address prepends a length prefix (0xd4
) to the address bytes (e.g., 0xd40655977feb2f289a4ab78af67bab0d17aab84367
).
Correct key: keccak256(0xd40655977feb2f289a4ab78af67bab0d17aab84367)
- differs from the raw hash.
Mismatch:
Provided: keccak256(raw 20 bytes)
- doesn’t match any trie node.
Expected: keccak256(RLP-encoded address)
- the actual path to SCRVUSD
’s account in the state trie.
Result: extractAccountFromProof()
fails to find the account, returning account.exists = false
, triggering a revert at require(account.exists)
.
Affected Functions:
verifyScrvusdByBlockHash()
and verifyScrvusdByStateRoot()
call _extractParametersFromProof()
, both failing due to this error.
Every verification attempt reverts at require(account.exists, "scrvUSD account does not exist")
, preventing _extractParametersFromProof()
from completing.
No parameters are extracted, so _updatePrice()
is never called on ScrvusdOracleV2
.
If never updated: ScrvusdOracleV2
remains at its initial state, misrepresenting scrvUSD’s true vault value.
If previously updated: Stale data persists, lagging behind Ethereum’s scrvUSD state.
Manual Code Review
Ethereum Documentation
Use RLP encoding to match the state trie key:
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.