In ScrvusdVerifierV1.sol
, the two verification methods verifyScrvusdByBlockHash
and verifyScrvusdByStateRoot
pass different timestamps to the update_price
function of ScrvusdOracleV2. The former uses the Ethereum block header timestamp (block_header.timestamp
), while the latter uses the scrvUSD
vault’s last_profit_update (params[5])
. This discrepancy can lead to minor variations in the oracle’s price calculations due to differences in how unlocked shares and parameter adjustments are computed, particularly when the block time and last_profit_update
diverge.
The issue arises from inconsistent timestamp arguments passed to the oracle:
In verifyScrvusdByBlockHash
:
Timestamp: block_header.timestamp
- the Ethereum block’s timestamp when the scrvUSD state was captured.
In verifyScrvusdByStateRoot
:
Timestamp: params[5]
- the last_profit_update
value from the scrvUSD vault’s storage (slot 40), indicating the last profit update time
Price Variation
Manual Code Analysis
Use block_header.timestamp
universally in the code.
- Sponsor Comments - State root oracles usually do not provide block.timestamp, so it's simply not available. That is why last_profit_update is intended. - In `update_price`, this value must be a future block, meaning this update is a state checked and allowed by the OOS verifier contracts. The impact is also increasingly limited given price is smoothen and any updates via the block hash `verifyScrvusdByBlockHash` can also update the prices appropriately, meaning the price will likely stay within safe arbitrage range aligning with protocol logic
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.