Oracle de prix on-chain · flux de prix d’actifs réels

Oracle de prix pour smart contracts : forex, or, indices et actions on-chain

Récupérez un rapport de prix signé depuis notre API et transmettez-le à votre contrat. Notre contrat vérificateur contrôle la signature on-chain, si bien que votre contrat peut faire confiance au prix sans faire confiance au messager.

Comment ça marche

  1. Récupérez un rapport signé : GET /oracle/report avec votre clé API.
  2. Soumettez-le dans votre transaction : notre contrat vérificateur contrôle la signature avec ecrecover.
  3. Utilisez le prix vérifié ; rejetez-le s’il est trop ancien pour votre cas d’usage.

Les rapports sont des données typées EIP-712 PriceReport(bytes32 feedId,int256 price,uint64 timestamp,uint64 validUntil,uint8 marketStatus,uint32 spreadBps), liées à une chaîne et à un contrat vérificateur (aucun rejeu ailleurs) et acceptées seulement jusqu’à validUntil, environ une minute après la signature (impossible d’accumuler des rapports favorables). Les prix sont le milieu entre achat et vente avec 8 décimales ; spreadBps est l’écart achat-vente. Quand vous soumettez un rapport dans votre propre transaction, vous payez ce gas. Les flux demandés sont aussi enregistrés on-chain de temps en temps par notre relayeur (lecture gratuite), mais vérifiez toujours l’âge d’un prix enregistré.

Heures de marché

Chaque rapport indique le statut du marché : OPEN (un prix en direct, datant d’au plus 60 secondes), CLOSED (le dernier prix officiel avant la clôture, identique pour tous, signé à tout moment tant que le marché est fermé) ou HALTED (cotation suspendue). getPriceNoOlderThan ne renvoie que des prix OPEN, si bien qu’un prix de clôture ne peut jamais passer pour un prix en direct. Les jetons adossés à des actifs devraient régler les ordres passés marché fermé au prochain prix OPEN (forward pricing, comme le font les fonds et les ETF).

Coupe-circuit

Chaque flux peut avoir un saut maximal autorisé. Un mouvement plus important n’est pas enregistré : le flux se met en pause jusqu’à ce que nous l’ayons vérifié et rouvert, si bien qu’un prix erroné ou manipulé n’atteint jamais votre contrat.

Flux

SymbolefeedId
AUDUSD0x5577fa17b1be8ae0f1517fe1864ea534d6992f3721000cdb6585b11e7046d5ec
EURGBP0xeaff3420d70d388655273db9b4f3000962445a6f0ea23ec1f04d843e4dbae4b0
EURUSD0x0730076c3c0f5da594eb635c5d5a22116233bdb2a9c2977279cc348b8b8ce917
GBPUSD0xd30842147b60fe333c2700bcae5eee6815b8529847955d19522858806bca8217
IEF0x309dab183458dd939568dca0d68bea45d34aa25d31fa47fc5f12030e8f227f4e
OILCash#0xe21b90a237aa0663c02092eca221a0098c6c477054a61d05ecd3692f6631f6ff
SHY0x78f1083af8e72ddefc2e66fad95680c38a953b3136f413c61ab40f99b72991bc
SPY0xcea23e8f56b5ac447ac08d57e0808e35f468a65f29bb659b3d48934481e7c67a
TLT0x4abd434857e07567d49487ccf888348e55d5cfc15498c09a9dbcba2820e40ee4
USDCAD0xa36f6cf3195abb4e93bf276660acee423f78878e6cfdbad0eab36e455afca97e
USDCHF0xd85af9ebd6fec6b317a7ac07f6d6455c4fc915cc8e1cfe19471faca002582907
USDJPY0x3d6c40e9d821c10e442cb3fc6cb1c589ffd8b906e734a1ab3b3f7d213ac395d6
USDSGD0x8a1375bd16e33aff9be7037f83e076defe9df6efea6d39a51d0b08f17ac9bc6d
XAGUSD0x67107df7f0e95594d9bf8ad8840bbb2ff95617123c227e10aab4d161dd6959b6
XAUUSD0xe21c86d8b6a127bfef214d88fdb0c279e55d27dd8c443733e46c8d3de3c98cd6

Réseaux

RéseauID de chaîneContrat vérificateur
Optimism100xaeF7f701acFB42267015D3F593ce17CF536Afd6B
Optimism Sepolia testnet111554200xBBf36E7Cd75494f28E02C5698EaD35fF4960a943

Adresse du signataire : 0x83fa2d8836525251FAd214A78A72038D0864f877. Liste lisible par machine : /oracle/feeds.

Intégrer

1. Récupérer un rapport signé

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

Renvoie report (le tuple encodé en ABI) et signature (65 octets) par symbole. Votre clé a besoin de la portée read:oracle.

2. Le vérifier dans votre contrat

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 ...
    }
}

Les consommateurs de type Chainlink peuvent lire un flux via le MarketApiFeedAdapter (latestRoundData(), AggregatorV3Interface).

Tarifs

5 crédit(s) par rapport signé, payé(s) sur votre solde API habituel. La lecture des prix déjà enregistrés on-chain est gratuite.

Cas d’usage de nos flux de prix on-chain

Pourquoi un oracle pull signé ?

Les oracles push se mettent à jour selon un calendrier et quelqu’un paie le gas de chaque mise à jour. Avec un oracle pull, votre contrat récupère un prix frais et signé cryptographiquement exactement quand il en a besoin : coût plus faible, données plus fraîches et la même vérification on-chain. Le statut du marché, l’écart achat-vente et l’expiration font partie de chaque rapport signé.

FAQ de l’oracle de prix

Qu’est-ce qu’un oracle de prix blockchain ?

Un oracle de prix apporte des prix de marché hors chaîne aux smart contracts. Notre oracle signe chaque prix avec une signature EIP-712 ; votre contrat la vérifie on-chain avec ecrecover avant de l’utiliser, si bien que le prix ne peut pas être falsifié en chemin.

Quels actifs couvrent les flux de prix ?

Paires de devises comme EUR/USD, métaux précieux comme l’or (XAU/USD) et l’argent, indices boursiers et actions individuelles, tels que publiés dans la liste des flux de cette page. Chaque flux a un feedId fixe (keccak256 du symbole).

Convient-il aux RWA et aux actifs tokenisés ?

Oui. Les rapports indiquent le statut du marché (ouvert, fermé, suspendu), si bien que les actions tokenisées, les matières premières et autres actifs réels peuvent appliquer un forward pricing en dehors des heures de marché au lieu de s’échanger sur un prix périmé.

L’oracle est-il compatible Chainlink ?

Chaque flux peut être lu via un adaptateur qui implémente l’AggregatorV3Interface de Chainlink (latestRoundData), si bien que le code DeFi existant qui lit des flux de prix de type Chainlink fonctionne avec un minimum de changements.

Comment la manipulation est-elle empêchée ?

Les rapports expirent au bout d’environ une minute et doivent être plus récents que le prix enregistré, un coupe-circuit par flux met un flux en pause après un saut anormal, et avec plusieurs courtiers le prix est la médiane de sources indépendantes, valeurs aberrantes retirées.

Qui paie les frais de gas ?

C’est un oracle pull : votre application soumet le rapport signé dans sa propre transaction et paie ce gas. Notre relayeur enregistre aussi de temps en temps on-chain les flux demandés ; la lecture des prix enregistrés est gratuite, mais vérifiez leur âge avant de les utiliser.

Quelles blockchains sont prises en charge ?

Toute chaîne EVM où le contrat vérificateur est déployé, par exemple Ethereum, Base, Arbitrum, Optimism, BNB Smart Chain et Polygon et leurs testnets ; la liste actuelle figure ci-dessus.

Recommandé : le modèle pull (des prix toujours frais)

Ne vous fiez pas au prix déjà stocké on-chain. Récupérez un rapport fraîchement signé et soumettez-le dans la même transaction qui l’utilise : votre contrat voit toujours le prix actuel, et vous ne payez que vos propres mises à jour.

// 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)
    }
}

Les champs report et signature du rapport fournis par l’API sont exactement les deux arguments de submit. Les rapports sont valables environ une minute, récupérez-les donc juste avant d’envoyer la transaction.

Avertissement. Les prix sont des données de marché indicatives issues de notre source, pas un lieu d’exécution. Les smart contracts qui déplacent des fonds sur la base d’un oracle doivent vérifier la fraîcheur, gérer les mises à jour manquantes et plafonner l’impact d’un prix erroné. Lisez les conditions avant de vous appuyer sur l’oracle en production.