> 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/ko/products/oracle-gateway.md).

# Oracle Gateway

Chainlink의 AggregatorV3Interface 뒤에 있는 Pyth 및 Switchboard 가격 피드.

Oracle Gateway는 Chainlink의 `AggregatorV3Interface`, 따라서 Rome으로 포팅되는 Ethereum 프로토콜은 기존 오라클 통합 코드를 그대로 유지합니다. **Oracle Gateway V2는 Hadrian과 Rubicon에 배포되어 있습니다**, 다만 레지스트리에는 Hadrian의 피드 주소만 나와 있고, 등록은 고객 포털에서 처리합니다. Rome이 운영하는 keeper가 캐시된 피드와 book 피드를 새로 고치지만, 모든 피드가 매 순간 최신인 것은 아닙니다 — [오늘 어떤 피드가 응답하는지](#which-feeds-answer-today) 아래에 자세히 설명되어 있습니다. 어댑터, 팩토리, 그리고 keeper 모델은 다음에 다룹니다 [rome-oracle-gateway](https://github.com/rome-protocol/rome-oracle-gateway) 저장소.

> **미리보기.** Oracle Gateway는 감사되지 않았습니다. 포털도 마찬가지로 말합니다: 프로덕션 가치 흐름에서는 사용하지 마세요.

## 문제

Ethereum DeFi는 Chainlink의 `AggregatorV3Interface`:

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

Solana의 오라클 제공자(Pyth, Switchboard)는 데이터 형식이 다릅니다. 적응 계층이 없으면 포팅된 모든 프로토콜마다 맞춤형 오라클 코드가 필요합니다.

## 해결책

Oracle Gateway V2는 다음과 같은 경량 어댑터 계약을 배포합니다:

1. Solana의 Pyth 또는 Switchboard 계정에서 가격 데이터를 직접 읽음(cross-state reads이며 CPI는 아님)
2. 온체인 데이터를 파싱함
3. 가격을 소수점 8자리로 정규화함
4. 표준 Chainlink를 노출 `AggregatorV3Interface`

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

// Ethereum의 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, registry v0.2.0: 0x567384ee000ca0418c386A73eC2b7466f9f99D6b
```

레지스트리는 GitHub에서 설치됩니다 (`npm install github:rome-protocol/rome-registry#v0.2.0`). 피드 키에는 뒤에 어떤 어댑터 유형이 있는지 나타내는 접미사가 붙습니다. 다음을 참조하세요 [레지스트리의 피드 키](#feed-keys-in-the-registry) 하나를 선택하기 전에.

2. **읽어 보세요** 프로토콜이 이미 사용하는 인터페이스로 — `IAggregatorV3Interface(solUsd).latestRoundData()`. 오래되었거나 초기화되지 않은 피드는 **되돌아갑니다** 고정된 가격을 제공하는 대신 실패합니다.
3. **여러 피드를 한 번에?** `BatchReader.getLatestPrices(adapters[])` (Hadrian, registry v0.2.0: `0x2869f0a96572e7fb15036656e9a32fd17346499b`) — 그리고 `getFeedHealth(adapters[])` 그들에 의존하기 전에 확인하세요. 캐시된 어댑터는 각 소비자가 일반적인 `SLOAD`, 따라서 다중 피드 트랜잭션(다중 담보 대출, 포트폴리오 보기) 비용이 저렴하게 유지됩니다.

[cardo](https://github.com/rome-protocol/cardo) Hadrian에서 이 피드들을 읽습니다. 표면이 정확히 `AggregatorV3Interface`, 따라서 Compound 및 Aave 계열 프로토콜은 오라클 코드 변경 없이 이 피드를 사용할 수 있습니다 — 가격 피드 구성을 어댑터 주소로 지정하세요.

## 어댑터 유형

* **PythPullAdapter** — Pyth 가격 계정(price, confidence, EMA, publish time)을 읽습니다.
* **SwitchboardV3Adapter** — Switchboard 집계자 계정(price, timestamp; EMA 없음)을 읽습니다.
* **CachedPyth / CachedFeed 어댑터** — CU 효율적인 읽기를 위한 캐시 추적 변형입니다.
* **BookFeedAdapter** — 다음의 한 항목에 대한 읽기 전용 Chainlink 호환 뷰입니다: `PriceBook` 계약. 이 book은 등록된 모든 피드의 가격을 보관하며 일괄로 새로 고쳐집니다(새로 고침은 무허가 방식입니다). 각 피드의 어댑터는 자체 캐시를 보관하지 않습니다. 일시 중지된 항목은 바로 다음 오류와 함께 되돌립니다 `AdapterPaused`, 오래되기를 기다리지 않고 바로 실패합니다.

어댑터는 EIP-1167 최소 프록시 클론으로 배포됩니다: `OracleAdapterFactory` 는 Pyth, Switchboard 및 캐시된 어댑터를 클론하며, 각 `PriceBook` 은 자체 `BookFeedAdapter` 를 피드가 등록될 때 클론합니다. 이들은 다음과 함께 확장된 인터페이스를 노출합니다 `AggregatorV3Interface` (`latestPriceData`, `maxStaleness`, `oracleType`, 그리고 `metadata()` 는 상태 확인에 사용되는 표면입니다).

## 레지스트리의 피드 키

`getOracle(chainId).feeds` 는 자산당 여러 개의 키를 가집니다. 키의 접미사가 어댑터 유형을 나타냅니다:

| 키                    | 어댑터 유형                               | 읽는 방식                                                         |
| -------------------- | ------------------------------------ | ------------------------------------------------------------- |
| `SOL/USD`            | 직접 Pyth (`PythPullAdapter`)          | 호출할 때마다 Pyth 계정을 파싱합니다.                                       |
| `SOL/USD-BOOK`       | `BookFeedAdapter`                    | 다음의 항목을 읽습니다: `PriceBook` keeper가 새로 고치는 항목.                  |
| `SOL/USD-CACHED`     | 캐시됨(다른 피드를 감쌈)                       | keeper가 새로 고치는 저장된 가격을 읽습니다.                                  |
| `SOL/USD-CACHEDPYTH` | 캐시된 Pyth (`CachedPythAdapter`)       | keeper가 새로 고치는 저장된 가격을 읽습니다.                                  |
| `SOL/USD-SB`         | Switchboard (`SwitchboardV3Adapter`) | 호출할 때마다 Switchboard 계정을 파싱합니다. 레지스트리는 이 항목들을 표시합니다 `retired`. |

어느 것을 사용할지는 체인에 따라 다릅니다. 먼저 다음 섹션을 확인하세요.

### 오늘 어떤 피드가 응답하는지

이는 읽기 전용 `latestRoundData()` 이 페이지를 작성할 당시 registry v0.2.0에 나열된 피드들에 대해 수행한 호출 결과입니다. devnet에서는 피드의 최신성이 분마다 달라지므로, 스냅샷으로 취급하고 사용할 예정인 피드에 대해 동일한 호출을 실행하세요.

* **Hadrian.** 직접 피드는 종종 오래됩니다: 반복 확인에서 대부분(BONK, BTC, ETH, JITOSOL, JTO, JUP, MSOL, USDC, USDT)은 다음 오류와 함께 되돌아갔습니다 `StalePriceFeed` 매번, 그리고 `SOL/USD` 일부 호출에서는 응답하고 다른 호출에서는 응답하지 않았습니다.  `-BOOK` 피드가 가장 안정적이었고 JTO를 제외한 모든 자산에서 모든 호출에 응답했습니다. JTO의 `-BOOK` 피드는 오래된 것으로 간주되어 되돌아갔습니다. 모든 `-CACHED` 및 `-CACHEDPYTH` 피드는 다음 오류와 함께 되돌아갔습니다 `UninitializedPriceFeed` (아무도 이를 새로 고치지 않았기 때문입니다), 그리고 `SOL/USD-SB` 다음 오류와 함께 되돌아갔습니다 `StalePriceFeed`. `-BOOK` 피드를 우선 선택하고, 실행하세요 `latestRoundData()` 사용하기 전에 선택한 피드에서.
* **Rubicon.** 레지스트리에는 Rubicon의 오라클 피드가 나와 있지 않으므로, 이 페이지에서는 이를 다루지 않습니다. 팩토리는 그곳에 배포되어 있으며(다음을 참조 [배포된 주소](#deployed-addresses)) 그리고 첫 번째 어댑터들은 응답하지만, 피드 주소는 레지스트리가 아니라 팩토리에서 확인하세요 (`adapterCount()` 및 `allAdapters(i)`) 레지스트리에서가 아니라 팩토리에서 확인하세요.

여기서의 revert는 의도된 동작입니다: 오래되었거나 초기화되지 않은 피드는 이전 가격을 반환하는 대신 크게 실패합니다. 이를 계약에서 처리하세요.

## 최신성 — 오라클 keeper

어댑터는 다음을 강제합니다: `maxStaleness` 윈도우: 만약 `block.timestamp - publishTime > maxStaleness`, 읽기는 revert됩니다. Solana 메인넷에서는 Pyth가 프로덕션 keeper를 운영합니다. Solana devnet(Hadrian이 있는 곳)에서는 Pyth의 푸셔가 best-effort이므로 Rome이 자체 **오라클 keeper** sidecar를 운영해 기반 Pyth 계정을 최신으로 유지하고, 캐시 및 book 피드를 새로 고칩니다. keeper가 모든 체인의 모든 피드를 항상 커버하는 것은 아닙니다(다음을 참조 [오늘 어떤 피드가 응답하는지](#which-feeds-answer-today)).

다음으로 피드 상태를 확인하세요 `BatchReader.getFeedHealth` (각 어댑터의 `metadata()`), 단순히 `latestRoundData` — 피드에 접근할 수 있어도 오래되었을 수 있습니다.

## 고객 포털

체인별로 피드를 등록하고 소비자를 구성하려면 다음을 통해 [Oracle Gateway 포털](https://oracle.testnet.romeprotocol.xyz/). 다음을 참조하세요 [포털 페이지](/ko/rome/oracle-gateway.md) 에서 다루는 내용을 확인하세요.

## 배포된 주소

체인별 표준 주소(팩토리, 어댑터 구현체, 그리고 실시간 피드)는 다음에 있습니다 [레지스트리](https://github.com/rome-protocol/rome-registry/tree/main/chains). `live` registry v0.2.0의 항목들(Hadrian에서는 버전 5.0.0이며, Rubicon 주소는 다음의 [컨트랙트 주소](/ko/reference/contract-addresses.md) 페이지); 다음을 참조하세요 [컨트랙트 목록 읽기](/ko/reference/contract-addresses.md#reading-the-contracts-list):

| 계약                   | Hadrian                                      | Rubicon                                      |
| -------------------- | -------------------------------------------- | -------------------------------------------- |
| OracleAdapterFactory | `0x52b008771fc95b4674a4f3533570b3d223f27f68` | `0x6a1340dd86c3951b6f13d9001b3951d56a2fe581` |
| BatchReader          | `0x2869f0a96572e7fb15036656e9a32fd17346499b` | `0x580dc0ecb226530ee8a90b57e0f0cd2555fb4f0f` |

## 제약 사항

* **과거 라운드 데이터 없음** — `getRoundData(roundId)` revert됩니다; 다음만 `latestRoundData()` 지원됩니다.
* **Switchboard EMA는 지원되지 않음** — EMA 데이터는 Pyth 전용입니다.
* **체인별 최신성 기준** — `maxStaleness` 는 시작 시 환경별로 설정됩니다: 직접(Pyth 읽기) 어댑터의 기본값은 약 60초이며, 캐시된 어댑터의 기본값은 3600초입니다(keeper가 이를 새로 고칠 때는 그보다 훨씬 더 자주 수행합니다).
* **파서 오프셋** 은 현재 Pyth/Switchboard 레이아웃을 기준으로 검증됩니다. 레이아웃이 바뀌면 재검증이 필요합니다.

## 다음 단계

* [Oracle Gateway 포털](/ko/rome/oracle-gateway.md) — 피드를 등록하고, 소비자를 구성하세요
* [컨트랙트 주소](/ko/reference/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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.rome.builders/ko/products/oracle-gateway.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
