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

No upper bound limit for _block_number parameter on ScrvusdOracleV2.vy::update_price leads to stuck price configuration

Summary

There is no upper bound limit check for _block_number ScrvusdOracleV2.vy::update_price call parameter
This allows caller to lock a price configuration for a really long period of time, and make it unable to change it later.

Vulnerability Details

Assume n = current blocknumber (block.number)
Verifier calls update_price with _block_number = n + 100_000
Now contract sets:
self.last_block_number = _block_number

If _block_number is too far away from current block, then price configuration cant be updated anymore until defined long time has passed because this condition:

@external
def update_price(
_parameters: uint256[ALL_PARAM_CNT], _ts: uint256, _block_number: uint256
) -> uint256:
#...
@> assert self.last_block_number <= _block_number, "Outdated"

Eg, suppose _block_number parameter = n = 80_000_000
If block time is 12 secs (as in ETH mainnet) this means that update time is locked for 30 years

n * 12 / (60*60*24*365)
30.441400304414003

Ie no further modification can be made until 30 years has passed.

Proof of Concept
The following PoC shows the described scenario:
A call to update_price is performed with _block_number parameter equal to ~30 years in block numbers (assuming 12 sec per block)
Next and attempt to change price configuration before 30 years has passed are performed, but will be reverted

Add code in tests/scrvusd/oracle/unitary/test_v2.py

def test_update_price_no_upper_limit_blocknumberMine(soracle, verifier, anne):
ts = boa.env.evm.patch.timestamp
price_1_5_parameters = [3, 0, 2, ts + 7 * 86400, 0, 0, 0]
price_0_5_parameters = [2, 0, 3, ts + 7 * 86400, 0, 0, 0]
price_0_x_parameters = [0, 0, 3, ts + 7 * 86400, 0, 0, 0]
with boa.env.prank(verifier):
# 1. Current block number = n
block_num: uint256 = soracle.last_block_number()
print("Current block number => ",block_num)
# 2. Call update_price with param
# _block_number = block_num + 80_000_000
# Price conf will be locked for ~ 30 years
soracle.update_price(
price_1_5_parameters,
ts + 100, # timestamp
block_num + 80_000_000, # block number
)
# 3. Try to modify price with a blocknumber prior to previously value set reverts
with boa.reverts():
soracle.update_price(
price_0_5_parameters,
ts + 100, # timestamp
block_num + 40_000_000, # block number
)

Exec test with:

pytest -s tests/scrvusd/oracle/unitary/test_v2.py

Note -s flag
The second call to update_price fails due to price configuration is locked for more than 30 years due to no upper limit on _block_number parameter on update_price

Impact

The lack of upper bond limit for _block_number ScrvusdOracleV2.vy::update_price parameter could lead to the inability to change price configuration for a very long periods of time

Tools Used

Manual Review

Recommendations

Implement an upper limit offset for _block_number parameter based on current block.number

Updates

Lead Judging Commences

0xnevi Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope
Assigned finding tags:

[invalid] finding-block-number-no-input-check

- Anything related to the output by the `BLOCK_HASH_ORACLE` is OOS per \[docs here]\(<https://github.com/CodeHawks-Contests/2025-03-curve?tab=readme-ov-file#blockhash-oracle>). - The PoC utilizes a mock `BLOCK_HASH_ORACLE`which is not representative of the one used by the protocol - Even when block hash returned is incorrect, the assumption is already explicitly made known in the docs, and the contract allows a subsequent update within the same block to update and correct prices - All state roots and proofs must be verified by the OOS `StateProofVerifier` inherited as `Verifier`, so there is no proof that manipulating block timestamp/block number/inputs can affect a price update - There seems to be a lot of confusion on the block hash check. The block hash check is a unique identifier of a block and has nothing to do with the state root. All value verifications is performed by the OOS Verifier contract as mentioned above

Support

FAQs

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