The ScrvusdOracleV2
contract initializes the price at a fixed value of 1 (10^18) regardless of the actual scrvUSD price on Ethereum mainnet at deployment time. This creates a significant discrepancy between the initial oracle price on the destination chain and the actual price on Ethereum, enabling price manipulation and breaking the fundamental security invariant of maintaining consistent prices across chains.
While the init
accepts an _initial_price
parameter, the comment "initial raw_price is 1" and the initialization of price_params
with total_idle=1
and total_supply=1
effectively sets the raw price to 1, regardless of the actual scrvUSD price on Ethereum at the time of deployment.
According to the project README, the primary purpose of this oracle is to ensure consistent pricing of scrvUSD across chains:
"To address this problem, we opted to have secondary scrvUSD markets on all chains where scrvUSD can be redeemed. Since the price of the asset is not stable, we cannot use a 'simple' stableswap-ng pool as the price of the asset would go up as the yield accrues."
The oracle's role is to "fetch scrvUSD vault parameters from Ethereum, and provide them on other chains, with the goal of being able to compute the growth rate in a safe (non-manipulable) and precise (no losses due to approximation) way."
But this has then been broken and we then have to wait until a prover sends in a valid block hash or stateroot to then update the price, this is unlike what's done in the case of the profit_max_unlock time, since it's set correctly to 7 days.
Since the actual scrvUSD
price on Ethereum is not exactly 1 at deployment time (which is highly likely as scrvUSD accrues yield), there will be an immediate price discrepancy between chains, which would then allow for arbitrage opportunities where attackers can exploit the price difference between chains, potentially draining liquidity from pools on the destination chain.
The impact is particularly severe cause protocol intends to deploy on any/all EVM known chains, so now post the initial deployment period on any new EVM chain that's to be supported by the and before the first price update occurs, we have a window where the price on the destination chain is completely disconnected from the actual price on Ethereum and this all depends on how long it takes the prover to send in the update.
Manual review
The initialization should use the actual scrvUSD
price from Ethereum at deployment time which the deployer
should in this case be trusted and correctly provide, this can also be easily done by passing in a params
array during deployment.
Alternatively, pricing should not be updated during init, and instead there should be a flag that allows for querying prices only after the first price update has occurred, in the price getters.
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.