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

Always 1 of the 2 verifier functions will revert

Summary

In some chains, 1 of the 2 Verifier's functions will not work as they are not implemented in the BLOCK_HASH_ORACLE.

Vulnerability Details

The ScrvusdVerifierV1 and ScrvusdVerifierV2 contracts implement 2 different ways to update the oracle:

  1. By block hash

  2. By state root

function verifyScrvusdByBlockHash(
bytes memory _block_header_rlp,
bytes memory _proof_rlp
) external returns (uint256) {
Verifier.BlockHeader memory block_header = Verifier.parseBlockHeader(_block_header_rlp);
require(block_header.hash != bytes32(0), "Invalid blockhash");
require(
@> block_header.hash == IBlockHashOracle(BLOCK_HASH_ORACLE).get_block_hash(block_header.number),
"Blockhash mismatch"
);
..
function verifyScrvusdByStateRoot(
uint256 _block_number,
bytes memory _proof_rlp
) external returns (uint256) {
@> bytes32 state_root = IBlockHashOracle(BLOCK_HASH_ORACLE).get_state_root(_block_number);
..

Each on of them calls a different function of the BLOCK_HASH_ORACLE contract, get_block_hash(...) or get_state_root(...). However, this contract doesn't implement both functions. Looking at the Block Hash Oracle code we can see that OptimismBlockHashOracle.vy implements the get_block_hash(...) function but not the get_state_root(...) one:

@view
@external
def get_block_hash(_number: uint256) -> bytes32:
"""
@notice Query the block hash of a block.
@dev Reverts for unknown block numbers or if not supported.
@param _number Number of the block to look for.
"""
block_hash: bytes32 = self.block_hash[_number]
if block_hash == empty(bytes32) and _number == convert(staticcall L1_BLOCK.number(), uint256):
# try fetching current data
block_hash = staticcall L1_BLOCK.hash()
assert block_hash != empty(bytes32)
return block_hash
@view
@external
def get_state_root(_number: uint256) -> bytes32:
"""
@notice Query the state root hash of a block.
@dev Reverts for unknown block numbers or if not supported.
@param _number Number of the block to look for.
"""
raise "NotImplemented"

SonicBlockHashOracle.vy and TaikoBlockHashOracle.vy don't implement the get_block_hash(...) function but do the get_state_root(...) one.

Impact

1 of the 2 functions of the verifiers will always revert, allowing only 1 way to update the oracle.

Tools Used

Manual review

Recommendations

Gracefully revert in the verifiers if the function is not implemented or not allow calling specific functions in specific chains.

Updates

Lead Judging Commences

0xnevi Lead Judge
3 months ago
0xnevi Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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