State root verification uses an outdated timestamp from the vault instead of the block’s actual timestamp.
File: ScrvusdVerifierV1.sol
In verifyScrvusdByStateRoot
, params[5]
(vault’s last_profit_update
) is used as _ts
, which may not reflect the block’s true timestamp.
The verifyScrvusdByStateRoot
method assumes the vault’s last_profit_update
(a storage variable in the scrvUSD contract) matches the block’s actual timestamp. However:
last_profit_update
is updated only when the vault processes profits, which may not align with the block’s timestamp.
If the vault has not processed profits recently, last_profit_update
becomes stale, leading to incorrect price extrapolation.
Block N
has a timestamp of 1700000000
.
The vault’s last_profit_update
is 1699990000
(1 hour old).
The oracle uses 1699990000
instead of 1700000000
to compute price_v1
/price_v2
.
The price is underestimated by 1 hour of yield, creating a risk-free arbitrage opportunity.
Price extrapolation uses stale timestamps, creating arbitrage opportunities due to inaccurate rates.
Manual review.
Fetch the block’s timestamp from the state root proof instead of relying on last_profit_update
- 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.