MetaOracle (Deviation Timelock)
The MetaOracleDeviationTimelock is a safety wrapper that selects between a primary and backup oracle. It switches to the backup when prices diverge beyond a threshold for a sustained challenge period, and switches back to the primary after prices reconverge for a sustained healing period. The contract implements Morpho’s IOracle interface, so downstream systems can treat it like any other oracle.
Deployments
Use the network-specific factory addresses to deploy new MetaOracleDeviationTimelock instances.
Explorer links reflect current public explorers; swap in preferred explorers if needed.
Audit and source
MetaOracleDeviationTimelock source: MetaOracleDeviationTimelock.sol
Factory source: MetaOracleDeviationTimelockFactory.sol
Audit report (Cantina): MetaOracleDeviationTimelock audit report
Core behavior
The contract starts with the primary oracle selected after initialization.
price()reflects whichever oracle is active (primary or backup).Deviation is computed as
abs(primary - backup) * 1e18 / average(primary, backup).A deviation can only trigger a switch after a timelocked challenge; reconvergence can only trigger a switch back after a timelocked healing.
Flow diagram
Primary → backup (challenge)
Backup → primary (healing)
Parameters
primaryOracle: preferred oracle used in normal conditions.backupOracle: fallback oracle used during deviation periods.deviationThreshold: maximum allowed relative deviation, scaled by1e18(e.g.,0.01e18for 1%).challengeTimelockDuration: seconds a deviation must persist before switching to backup.healingTimelockDuration: seconds prices must remain reconverged before switching back to primary.
Initialization rejects zero addresses, equal oracle addresses, non-positive thresholds, and any initial deviation above deviationThreshold.
Challenge flow (primary → backup)
Anyone calls
challenge()when the primary is active and prices are deviant.The contract starts a challenge timelock (
challengeExpiresAt).If prices reconverge before expiry, anyone can call
revokeChallenge().After expiry, anyone can call
acceptChallenge()while deviation still holds to switch to the backup.
Healing flow (backup → primary)
Anyone calls
heal()when the backup is active and prices have reconverged.The contract starts a healing timelock (
healingExpiresAt).If prices deviate again before expiry, anyone can call
revokeHealing().After expiry, anyone can call
acceptHealing()while prices are still converged to switch back to the primary.
Example: XAUT/USDT market
Setup
Primary oracle: XAUT priced from the XAU (gold) reference feed, USDT fixed at
1.Backup oracle: XAUT/USDT market TWAP (both legs from market pricing).
Flow
As long as the gold reference and the XAUT market price are close, the MetaOracle uses the primary oracle.
If XAUT trades away from the gold reference (or USDT drifts), the deviation exceeds the threshold and
challenge()starts the timelock.If the deviation persists through the challenge timelock,
acceptChallenge()switches pricing to the market TWAP backup.Once the market price reconverges with the gold reference for the healing timelock,
acceptHealing()switches back to the primary.
Factory
MetaOracleDeviationTimelock instances are deployed by MetaOracleDeviationTimelockFactory using EIP-1167 clones. Each deployment emits MetaOracleDeployed with the proxy address, implementation, oracle pair, threshold, and timelock durations.
Last updated