> For the complete documentation index, see [llms.txt](https://docs.rome.builders/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rome.builders/zh/chan-pin/oracle-gateway.md).

# Oracle Gateway

Oracle Gateway 通过 Chainlink 的 Solana 原生价格源（Pyth、Switchboard V3） `AggregatorV3Interface`，因此迁移到 Rome 的以太坊协议可以保留现有的预言机集成代码。 **Oracle Gateway V2 已在每条公有链上线**，并配备了一个确保价格源新鲜度的 keeper 以及用于注册的客户门户。适配器、工厂和 keeper 模型详见 [rome-oracle-gateway](https://github.com/rome-protocol/rome-oracle-gateway) 仓库。

## 问题

以太坊 DeFi 预期使用 Chainlink 的 `AggregatorV3Interface`:

```solidity
(, int256 price,,,) = priceFeed.latestRoundData();
```

Solana 的预言机提供方（Pyth、Switchboard）具有不同的数据格式。如果不做适配，每个迁移后的协议都需要自定义预言机代码。

## 解决方案

Oracle Gateway V2 部署轻量级适配器合约，它们：

1. 直接从 Solana 上的 Pyth 或 Switchboard 账户读取价格数据（跨状态读取，而非 CPI）
2. 解析链上数据
3. 将价格标准化为 8 位小数
4. 暴露标准的 Chainlink `AggregatorV3Interface`

```solidity
import {IAggregatorV3Interface} from "@rome-protocol/rome-solidity/contracts/oracle/IAggregatorV3Interface.sol";

// 与以太坊上的 Chainlink 相同的接口
(, int256 price,,,) = IAggregatorV3Interface(ADAPTER).latestRoundData();
// price = 8 位小数的 SOL/USD（例如 15000000000 = $150.00）
```

## 通过三步接入一个价格源

1. **从注册表中解析适配器地址** —— 切勿硬编码：

```ts
import { getOracle } from "@rome-protocol/registry";
const solUsd = getOracle(200010).feeds["SOL/USD"].address;
// Hadrian 今日：0x76b92646D63FB1AFEa687C7Dac48b437bF99C1B4
```

2. **读取它** 使用你的协议已在使用的接口—— `IAggregatorV3Interface(solUsd).latestRoundData()`。过时或未初始化的价格源 **会回退** 而不是返回冻结价格。
3. **一次处理多个价格源？** `BatchReader.getLatestPrices(adapters[])` （Hadrian： `0x306d670dff7f51ae33f263f5122bd2b18d98adc7`）——并且 `getFeedHealth(adapters[])` 在你依赖它们之前先检查它们的健康状况。缓存适配器使每个消费者读取一个普通的 `SLOAD`，因此多价格源交易（多抵押借款、组合视图）依然低成本。

[cardo](https://github.com/rome-protocol/cardo) 如今已在生产环境中消费这些价格源。由于其接口完全与 `AggregatorV3Interface`，因此 Compound 和 Aave 级别的协议可以 **可直接接入** —— 将其价格源配置指向适配器地址；其预言机代码无需任何更改。

## 适配器类型

* **PythPullAdapter** —— 读取 Pyth 价格账户（价格、置信度、EMA、发布时间）。
* **SwitchboardV3Adapter** —— 读取 Switchboard 聚合器账户（价格、时间戳；不含 EMA）。
* **CachedPyth / CachedFeed 适配器** —— 用于高 CU 效率读取的缓存跟踪变体。

适配器由 `OracleAdapterFactory` 以 EIP-1167 最小代理克隆方式部署，并与 `AggregatorV3Interface` (`latestPriceData`, `maxStaleness`, `oracleType`一起暴露扩展接口，以及一个 `metadata()` 接口（用于健康检查）。

## 新鲜度——预言机 keeper

适配器强制执行一个 `maxStaleness` 时间窗口：如果 `block.timestamp - publishTime > maxStaleness`，读取会回退。在 Solana 主网，Pyth 运行生产级 keeper。在 Solana devnet（公共链所在之处），Pyth 的推送器仅尽力而为，因此 Rome 运行自己的 **预言机 keeper** 旁车服务，以保持底层 Pyth 账户的最新状态。系统会监控新鲜度并在异常时告警。

使用以下方式检查价格源健康状态： `BatchReader.getFeedHealth` （它会读取每个适配器的 `metadata()`），而不只是 `latestRoundData` —— 一个价格源可能可访问但已过期。

## 客户门户

通过以下方式按链注册价格源并配置消费者： [Oracle Gateway 门户](https://oracle.testnet.romeprotocol.xyz/)。请参阅 [门户页面](/zh/rome-shang-de-ying-yong/oracle-gateway.md) 了解其覆盖内容。

## 已部署地址

每条链的规范地址（工厂、适配器实现和线上价格源）位于 [注册表](https://github.com/rome-protocol/rome-registry/tree/main/chains)。主要工厂：

| 合约                   | Hadrian                                      | Martius                                      |
| -------------------- | -------------------------------------------- | -------------------------------------------- |
| OracleAdapterFactory | `0xe68e7bc697010c73f1798b356f8ae2f0ba1319db` | `0xbc06fe9603a02ff4aead265c253f5c6303ee5fbb` |
| BatchReader          | `0x306d670dff7f51ae33f263f5122bd2b18d98adc7` | `0xc5e6d932bfd2b4da27643848063905f46861fae8` |

## 限制

* **无历史轮次数据** — `getRoundData(roundId)` 会回退；仅 `latestRoundData()` 受支持。
* **不支持 Switchboard EMA** —— EMA 数据仅适用于 Pyth。
* **按链设置的过期时间** — `maxStaleness` 在启动时按环境设置：直接（读取 Pyth）适配器默认为约 60 秒；缓存适配器默认为 3600 秒（keeper 刷新频率要高得多——目前在 devnet/testnet 上约为 25 秒）。
* **解析器偏移量** 会根据当前的 Pyth/Switchboard 布局进行验证；布局变更需要重新验证。

## 下一步

* [Oracle Gateway 门户](/zh/rome-shang-de-ying-yong/oracle-gateway.md) —— 注册价格源，配置消费者
* [合约地址](/zh/can-kao-wen-dang/contract-addresses.md) —— 预编译合约和按链地址


---

# 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://docs.rome.builders/zh/chan-pin/oracle-gateway.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.
