On-chain оракул цен · ценовые фиды реальных активов

Оракул цен для смарт-контрактов: валюты, золото, индексы и акции on-chain

Получите подписанный ценовой отчёт из нашего API и передайте его в контракт. Наш контракт-верификатор проверяет подпись on-chain, поэтому ваш контракт может доверять цене, не доверяя посреднику.

Как это работает

  1. Получите подписанный отчёт: GET /oracle/report с вашим ключом API.
  2. Отправьте его в своей транзакции: наш контракт-верификатор проверяет подпись через ecrecover.
  3. Используйте проверенную цену; отклоните её, если она слишком старая для вашей задачи.

Отчёты — это типизированные данные EIP-712 PriceReport(bytes32 feedId,int256 price,uint64 timestamp,uint64 validUntil,uint8 marketStatus,uint32 spreadBps), привязанные к одной сети и одному контракту-верификатору (без повторного использования в другом месте) и принимаемые только до validUntil, примерно через минуту после подписи (выгодные отчёты нельзя копить). Цены — середина между bid и ask с 8 знаками после запятой; spreadBps — спред bid-ask. Когда вы отправляете отчёт в собственной транзакции, вы платите за этот газ. Востребованные фиды также время от времени сохраняются on-chain нашим релейером (чтение бесплатно), но всегда проверяйте возраст сохранённой цены.

Торговые часы

Каждый отчёт указывает статус рынка: OPEN (живая цена не старше 60 секунд), CLOSED (официальная последняя цена перед закрытием, одинаковая для всех, подписывается в любой момент, пока рынок закрыт) или HALTED (торги остановлены). getPriceNoOlderThan возвращает только цены OPEN, поэтому цена закрытия никогда не сойдёт за живую. Токены, обеспеченные активами, должны исполнять ордера, поданные при закрытом рынке, по следующей цене OPEN (форвардное ценообразование, как у фондов и ETF).

Стоп-механизм

Для каждого фида можно задать максимально допустимый скачок. Более сильное движение не сохраняется: фид приостанавливается, пока мы не проверим и не откроем его снова, поэтому неверная или манипулятивная цена никогда не попадёт в ваш контракт.

Фиды

СимволfeedId
AUDUSD0x5577fa17b1be8ae0f1517fe1864ea534d6992f3721000cdb6585b11e7046d5ec
EURGBP0xeaff3420d70d388655273db9b4f3000962445a6f0ea23ec1f04d843e4dbae4b0
EURUSD0x0730076c3c0f5da594eb635c5d5a22116233bdb2a9c2977279cc348b8b8ce917
GBPUSD0xd30842147b60fe333c2700bcae5eee6815b8529847955d19522858806bca8217
IEF0x309dab183458dd939568dca0d68bea45d34aa25d31fa47fc5f12030e8f227f4e
OILCash#0xe21b90a237aa0663c02092eca221a0098c6c477054a61d05ecd3692f6631f6ff
SHY0x78f1083af8e72ddefc2e66fad95680c38a953b3136f413c61ab40f99b72991bc
SPY0xcea23e8f56b5ac447ac08d57e0808e35f468a65f29bb659b3d48934481e7c67a
TLT0x4abd434857e07567d49487ccf888348e55d5cfc15498c09a9dbcba2820e40ee4
USDCAD0xa36f6cf3195abb4e93bf276660acee423f78878e6cfdbad0eab36e455afca97e
USDCHF0xd85af9ebd6fec6b317a7ac07f6d6455c4fc915cc8e1cfe19471faca002582907
USDJPY0x3d6c40e9d821c10e442cb3fc6cb1c589ffd8b906e734a1ab3b3f7d213ac395d6
USDSGD0x8a1375bd16e33aff9be7037f83e076defe9df6efea6d39a51d0b08f17ac9bc6d
XAGUSD0x67107df7f0e95594d9bf8ad8840bbb2ff95617123c227e10aab4d161dd6959b6
XAUUSD0xe21c86d8b6a127bfef214d88fdb0c279e55d27dd8c443733e46c8d3de3c98cd6

Сети

СетьID сетиКонтракт-верификатор
Optimism100xaeF7f701acFB42267015D3F593ce17CF536Afd6B
Optimism Sepolia тестнет111554200xBBf36E7Cd75494f28E02C5698EaD35fF4960a943

Адрес подписанта: 0x83fa2d8836525251FAd214A78A72038D0864f877. Машиночитаемый список: /oracle/feeds.

Интеграция

1. Получите подписанный отчёт

curl -H "Authorization: Bearer $API_KEY" \
  "https://api.marketapi.app/v1/oracle/report?symbols=EURUSD&chain_id=10"

Возвращает report (ABI-кодированный кортеж) и signature (65 байт) для каждого символа. Ключу нужна область read:oracle.

2. Проверьте его в своём контракте

interface IMarketApiOracle {
    struct PriceReport { bytes32 feedId; int256 price; uint64 timestamp; uint64 validUntil;
                         uint8 marketStatus; uint32 spreadBps; }
    function submit(PriceReport calldata r, bytes calldata sig) external returns (bool);  // verifies, stores if newer
    function getPriceNoOlderThan(bytes32 feedId, uint256 maxAge)
        external view returns (int256 price, uint64 timestamp);   // OPEN and fresh only, else reverts
    function getPrice(bytes32 feedId) external view
        returns (int256 price, uint64 timestamp, uint8 marketStatus, uint32 spreadBps);   // incl. CLOSED
}

contract MyVault {
    IMarketApiOracle immutable oracle;
    bytes32 constant EURUSD = keccak256("EURUSD");
    constructor(IMarketApiOracle o) { oracle = o; }

    function act(IMarketApiOracle.PriceReport calldata r, bytes calldata sig) external {
        oracle.submit(r, sig);                                       // reverts on a bad signature
        (int256 price, ) = oracle.getPriceNoOlderThan(EURUSD, 60);   // 8 decimals
        // ... use price ...
    }
}

Потребители в стиле Chainlink могут читать фид через MarketApiFeedAdapter (latestRoundData(), AggregatorV3Interface).

Цены

кредитов за подписанный отчёт: 5, списываются с обычного баланса API. Чтение цен, уже сохранённых on-chain, бесплатно.

Сценарии использования наших on-chain ценовых фидов

Почему подписанный pull-оракул?

Push-оракулы обновляются по расписанию, и кто-то платит газ за каждое обновление. С pull-оракулом ваш контракт получает свежую криптографически подписанную цену ровно тогда, когда она нужна: ниже затраты, свежее данные и та же on-chain проверка. Статус рынка, спред bid-ask и срок действия входят в каждый подписанный отчёт.

Вопросы об оракуле цен

Что такое блокчейн-оракул цен?

Оракул цен доставляет внесетевые рыночные цены в смарт-контракты. Наш оракул подписывает каждую цену подписью EIP-712; ваш контракт проверяет её on-chain через ecrecover перед использованием, поэтому цену нельзя подделать в пути.

Какие активы охватывают ценовые фиды?

Валютные пары, например EUR/USD, драгоценные металлы, например золото (XAU/USD) и серебро, фондовые индексы и отдельные акции — согласно списку фидов на этой странице. У каждого фида фиксированный feedId (keccak256 от символа).

Подходит ли он для RWA и токенизированных активов?

Да. Отчёты содержат статус рынка (открыт, закрыт, торги остановлены), поэтому токенизированные акции, сырьё и другие реальные активы могут применять форвардное ценообразование вне торговых часов, а не торговаться по устаревшей цене.

Совместим ли оракул с Chainlink?

Каждый фид можно читать через адаптер, реализующий Chainlink AggregatorV3Interface (latestRoundData), поэтому существующий DeFi-код, читающий ценовые фиды в стиле Chainlink, работает с минимальными изменениями.

Как предотвращается манипуляция?

Отчёты истекают примерно через минуту и должны быть новее сохранённой цены, стоп-механизм для каждого фида приостанавливает его после аномального скачка, а при нескольких брокерах цена — это медиана независимых источников без выбросов.

Кто платит за газ?

Это pull-оракул: ваше приложение отправляет подписанный отчёт в собственной транзакции и платит за этот газ. Наш релейер также время от времени сохраняет востребованные фиды on-chain; чтение сохранённых цен бесплатно, но перед использованием проверяйте их возраст.

Какие блокчейны поддерживаются?

Любая EVM-сеть, где развёрнут контракт-верификатор, например Ethereum, Base, Arbitrum, Optimism, BNB Smart Chain и Polygon и их тестнеты; актуальный список приведён выше.

Рекомендуется: pull-схема (всегда свежие цены)

Не полагайтесь на цену, уже сохранённую on-chain. Получите свежеподписанный отчёт и отправьте его в той же транзакции, которая его использует: ваш контракт всегда видит текущую цену, а вы платите только за свои обновления.

// 1) off-chain: GET https://api.marketapi.app/v1/oracle/report?symbols=EURUSD&chain_id=CHAIN_ID  (header: Authorization: Bearer KEY)
// 2) on-chain: verify, store and use the report atomically
interface IMarketApiOracle {
    struct PriceReport { bytes32 feedId; int256 price; uint64 timestamp; uint64 validUntil; uint8 marketStatus; uint32 spreadBps; }
    function submit(PriceReport calldata r, bytes calldata sig) external returns (bool);
    function getPriceNoOlderThan(bytes32 feedId, uint256 maxAge) external view returns (int256 price, uint64 timestamp);
}

contract MyVault {
    IMarketApiOracle immutable oracle;
    bytes32 constant EURUSD = keccak256("EURUSD");
    constructor(IMarketApiOracle o) { oracle = o; }

    function settle(IMarketApiOracle.PriceReport calldata r, bytes calldata sig) external {
        oracle.submit(r, sig);                                         // ignored if an equal/newer price is stored
        (int256 price, ) = oracle.getPriceNoOlderThan(EURUSD, 60);    // reverts unless OPEN and fresh
        // ... use price (8 decimals)
    }
}

Поля report и signature отчёта из API — это ровно два аргумента submit. Отчёты действуют около минуты, поэтому получайте их прямо перед отправкой транзакции.

Предупреждение о рисках. Цены — это индикативные рыночные данные из нашего источника, а не площадка исполнения. Смарт-контракты, перемещающие средства на основе любого оракула, должны проверять актуальность, обрабатывать пропущенные обновления и ограничивать влияние неверной цены. Прочтите условия, прежде чем полагаться на оракул в продакшене.