> For the complete documentation index, see [llms.txt](https://steakhouse.financial/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://steakhouse.financial/docs/products/zh/infrastructure/metaoracle.md).

# MetaOracle（偏差时间锁）

该 `MetaOracleDeviationTimelock` 是一个安全封装器，用于在主预言机和备用预言机之间进行选择。它会在价格分歧在持续的挑战期内超过阈值时切换到备用预言机，并在价格在持续的恢复期内重新收敛后切回主预言机。该合约实现了 Morpho 的 `IOracle` 接口，因此下游系统可以将其视为任何其他预言机。

### 部署

使用与网络相关的工厂地址来部署新的 MetaOracleDeviationTimelock 实例。

| 链        | MetaOracle 工厂                                                                                                                       |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Ethereum | [`0x44d049eEd4AD33807859C45bBd3a8eb47917a9F4`](https://etherscan.io/address/0x44d049eEd4AD33807859C45bBd3a8eb47917a9F4)             |
| Base     | [`0x507f940234005f7c49dfE2F27E361C3b66Fb31CF`](https://basescan.org/address/0x507f940234005f7c49dfE2F27E361C3b66Fb31CF)             |
| Arbitrum | [`0x4f3F56A045a2D33ceEf1D1fD5F4C776b8bFb2168`](https://arbiscan.io/address/0x4f3F56A045a2D33ceEf1D1fD5F4C776b8bFb2168)              |
| Katana   | [`0x53A30343c8A51d685d17c1c40AAe8e76D2B79b68`](https://katanascan.com/address/0x53A30343c8A51d685d17c1c40AAe8e76D2B79b68)           |
| Polygon  | [`0xd058Fc46edd745B6c883Ef3F775669039235753d`](https://polygonscan.com/address/0xd058Fc46edd745B6c883Ef3F775669039235753d)          |
| Monad    | [`0x1C1FD6dc5D84C16cD152aC2E91F80327FE3aEd9F`](https://monadvision.com/address/0x1C1FD6dc5D84C16cD152aC2E91F80327FE3aEd9F)          |
| Unichain | [`0xf1BaEC963675A367E3ADe06A531B6407D78ab2A3`](https://uniscan.xyz/address/0xf1BaEC963675A367E3ADe06A531B6407D78ab2A3)              |
| HyperEVM | [`0x9fAE9968e4e68bEE5ddcb48bb68Fb27CC57ff384`](https://explorer.hyperliquid.xyz/address/0x9fAE9968e4e68bEE5ddcb48bb68Fb27CC57ff384) |

浏览器链接反映的是当前公开的区块浏览器；如有需要，可替换为首选的区块浏览器。

### 审计与源码

* MetaOracleDeviationTimelock 源码： [MetaOracleDeviationTimelock.sol](https://github.com/Steakhouse-Financial/steakhouse-oracles/blob/36385342274f71999b66c79c4475234a39ba9a01/src/MetaOracleDeviationTimelock.sol)
* 工厂源码： [MetaOracleDeviationTimelockFactory.sol](https://github.com/Steakhouse-Financial/steakhouse-oracles/blob/36385342274f71999b66c79c4475234a39ba9a01/src/MetaOracleDeviationTimelockFactory.sol)
* 审计报告（Cantina）： [MetaOracleDeviationTimelock 审计报告](https://github.com/Steakhouse-Financial/steakhouse-oracles/blob/5ce0e80adb69bc06f5b390032150e7ea41d30c02/audits/2025-06-23-metaoracledeviationtimelock-cantina-managed-review.pdf)

### 核心行为

* 合约在初始化后会以主预言机作为默认选择。
* `price()` 返回当前处于激活状态的任一预言机（主预言机或备用预言机）的价格。
* 偏差的计算方式为 `abs(primary - backup) * 1e18 / average(primary, backup)`.
* 只有在经过带时间锁的挑战之后，偏差才可触发切换；只有在经过带时间锁的恢复之后，重新收敛才可触发切回。

### 流程图

**主 → 备（挑战）**

{% @mermaid/diagram content="%%{init: {'themeVariables': {'fontSize': '13px'}, 'flowchart': {'nodeSpacing': 20, 'rankSpacing': 30}}}%%
flowchart LR
Primary\["Primary active"] --> Deviate{"Deviation > threshold?"}
Deviate -- "No" --> Primary
Deviate -- "Yes" --> Challenge\["challenge() starts timelock"]
Challenge --> ChallengeEnd{"After challengeTimelockDuration"}
ChallengeEnd -- "Deviation cleared" --> Primary
ChallengeEnd -- "Still deviant" --> Backup\["acceptChallenge() -> backup"]

" %}

**备 → 主（恢复）**

{% @mermaid/diagram content="%%{init: {'themeVariables': {'fontSize': '13px'}, 'flowchart': {'nodeSpacing': 20, 'rankSpacing': 30}}}%%
flowchart LR
Backup\["Backup active"] --> Reconverge{"Prices reconverged?"}
Reconverge -- "No" --> Backup
Reconverge -- "Yes" --> Heal\["heal() starts timelock"]
Heal --> HealEnd{"After healingTimelockDuration"}
HealEnd -- "Deviation returns" --> Backup
HealEnd -- "Still converged" --> Primary\["acceptHealing() -> primary"]" %}

### 参数

* `primaryOracle`：正常情况下使用的首选预言机。
* `backupOracle`：在偏差期间使用的备用预言机。
* `deviationThreshold`：允许的最大相对偏差，按 `1e18` 进行缩放（例如， `0.01e18` 表示 1%）。
* `challengeTimelockDuration`：偏差在切换到备用预言机之前必须持续的秒数。
* `healingTimelockDuration`：价格在切回主预言机之前必须保持重新收敛的秒数。

初始化会拒绝零地址、相同的预言机地址、非正阈值，以及任何高于 `deviationThreshold`.

### 挑战流程（主 → 备）

1. 任何人都可以在主预言机处于激活状态且价格出现偏差时调用 `challenge()` 。
2. 合约会启动一个挑战时间锁（`challengeExpiresAt`).
3. 如果在到期前价格重新收敛，任何人都可以调用 `revokeChallenge()`.
4. 在到期后，任何人都可以调用 `acceptChallenge()` ，只要偏差仍然存在，就会切换到备用预言机。

### 恢复流程（备 → 主）

1. 任何人都可以在主预言机处于激活状态且价格出现偏差时调用 `heal()` ，当备用预言机处于激活状态且价格已经重新收敛时调用。
2. 合约会启动一个恢复时间锁（`healingExpiresAt`).
3. 如果在到期前价格再次出现偏差，任何人都可以调用 `revokeHealing()`.
4. 在到期后，任何人都可以调用 `acceptHealing()` ，只要价格仍然收敛，就会切回主预言机。

### 示例：XAUT/USDT 市场

**设置**

* 主预言机：XAUT 价格来自 XAU（金）参考馈送，USDT 固定为 `1`.
* 备用预言机：XAUT/USDT 市场 TWAP（两条腿都来自市场定价）。

**流程**

1. 只要黄金参考价格与 XAUT 市场价格接近，MetaOracle 就会使用主预言机。
2. 如果 XAUT 脱离黄金参考价格（或 USDT 出现漂移），偏差超过阈值，并且 `challenge()` 启动时间锁。
3. 如果偏差在挑战时间锁期间持续存在， `acceptChallenge()` 会将定价切换到市场 TWAP 备用预言机。
4. 一旦市场价格在恢复时间锁期间与黄金参考重新收敛， `acceptHealing()` 会切回主预言机。

{% @mermaid/diagram content="sequenceDiagram
participant User as Any caller
participant Meta as MetaOracle
participant Primary as "Primary (XAU ref, USDT=1)"
participant Backup as "Backup (XAUT/USDT TWAP)"

```
Note over Meta: Starts on primary
Meta->>Primary: price()
User->>Meta: challenge() when deviation > threshold
Note over Meta: Wait challengeTimelockDuration
User->>Meta: acceptChallenge() if still deviant
Note over Meta: Switches to backup
Meta->>Backup: price()
User->>Meta: heal() when prices reconverge
Note over Meta: Wait healingTimelockDuration
User->>Meta: acceptHealing() if still converged
Note over Meta: Switches back to primary
Meta->>Primary: price()
```

" %}

### 工厂

MetaOracleDeviationTimelock 实例由 `MetaOracleDeviationTimelockFactory` 使用 EIP-1167 克隆部署。每次部署都会发出 `MetaOracleDeployed` 事件，其中包含代理地址、实现合约、预言机对、阈值以及时间锁持续时间。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://steakhouse.financial/docs/products/zh/infrastructure/metaoracle.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
