Oracles
Les oracles sont des flux de données qui connectent Ethereum aux informations hors chaîne du monde réel pour vous permettre d’interroger les données dans vos contrats intelligents. Par exemple, les DApps de marchés prédictifs utilisent les oracles pour régler des paiements en fonction des événements. Un marché prédictif peut vous demander de miser vos ETH sur le prochain président des États-Unis. Ils utiliseront un oracle pour confirmer le résultat et rémunérer les gagnants.
Prérequis
Assurez-vous d'avoir compris en quoi consistent les nœuds, les mécanismes de consensus et l' anatomie des contrats intelligents, et en particulier les événements.
Qu'est ce qu'un oracle ?
Un oracle est un pont entre la blockchain et le monde réel. Ils agissent sur la blockchain comme des API que vous pouvez interroger pour obtenir des informations dans vos contrats intelligents. Il peut s'agir de n'importe quoi, d'informations de prix aux bulletins météorologiques.
Pourquoi sont-ils nécessaires ?
Avec une blockchain comme Ethereum, tous les nœuds du réseau sont nécessaires pour pouvoir rejouer chaque transaction et finir avec le même résultat garanti. Les API introduisent des données potentiellement variables. Si vous envoyez à quelqu'un un montant d'ETH basé sur une valeur convenue en $USD via une API de prix, la requête retournera un résultat différent d'un jour sur l'autre. Sans parler du fait que l'API pourrait être piratée ou dépréciée. Dans ce cas, les nœuds du réseau ne pourraient pas se mettre d'accord sur l'état actuel d'Ethereum, brisant ainsi le consensus.
Les oracles résolvent ce problème en publiant les données sur la blockchain. Ainsi, tout nœud rejouant la transaction utilisera les mêmes données immuables qui ont été publiées pour que tout le monde puisse les voir. Pour faire cela, un oracle est comprend généralement un contrat intelligent et des composants hors chaîne qui peuvent interroger les API, puis envoyer périodiquement des transactions pour mettre à jour les données du contrat intelligent.
Sécurité
Un oracle n'est aussi sûr que sa ou ses sources de données. Si une DApp utilise Uniswap comme oracle pour son flux de prix ETH/DAI, il est possible pour un attaquant de déplacer le prix sur Uniswap afin de manipuler la compréhension du prix actuel par la DApps. Une façon de combattre cela est l'utilisation d'un un système de flux comme celui de MakerDAO, qui rassemble les données de prix à partir d'un certain nombre de flux de prix externes au lieu de dépendre d'une seule source.
Utilisation
Oracles en tant que service
Les sites comme celui de Chainlink proposent des oracles sous forme de service. Ils ont des infrastructures qui vous permettent :
- d'obtenir des flux de prix de cryptomonnaies dans votre contrat ;
- de générer des nombres aléatoires vérifiables (utile pour les jeux) ;
- d'appeler des API externes. Nouvelle utilisation possible : la vérification des réserves WBTC.
Voici un exemple de la façon d'obtenir le dernier prix de l'ETH dans votre contrat intelligent en utilisant un flux de prix Chainlink :
1pragmatima solidité ^0.6.7;23import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface. ol";45contrat PriceConsumerV3 {67 AggregatorV3Interface interne priceFeed ;89 /**10 * Réseau: Kovan11 * Aggregator: ETH/USD12 * Adresse: 0x9326BFA02ADD2366b30bacB125260Af64103133113 */14 constructor() publique {15 priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);16 }1718 /**19 * Renvoie le dernier prix20 */21 function getLatestPrice() public view returns (int) {22 (23 uint80 roundID,24 int prix,25 uint startedAt,26 uint horodatage,27 uint80 answeredInRound28 ) = priceFeed. atestRoundData();29 prix de retour;30 }31}32Afficher toutCopier
Services d'oracle
Créer un contrat intelligent oracle
Voici un exemple de contrat oracle créé par Pedro Costa. Vous pouvez trouver d'autres annotations dans son article " Implementing a Blockchain Oracle on Ethereum".
1pragma solidity >=0.4.21 <0.6.0;23contract Oracle {4 Request[] requests; //list of requests made to the contract5 uint currentId = 0; //increasing request id6 uint minQuorum = 2; //minimum number of responses to receive before declaring final result7 uint totalOracleCount = 3; // Hardcoded oracle count89 // defines a general api request10 struct Request {11 uint id; //request id12 string urlToQuery; //API url13 string attributeToFetch; //json attribute (key) to retrieve in the response14 string agreedValue; //value from key15 mapping(uint => string) anwers; //answers provided by the oracles16 mapping(address => uint) quorum; //oracles which will query the answer (1=oracle hasn't voted, 2=oracle has voted)17 }1819 //event that triggers oracle outside of the blockchain20 event NewRequest (21 uint id,22 string urlToQuery,23 string attributeToFetch24 );2526 //triggered when there's a consensus on the final result27 event UpdatedRequest (28 uint id,29 string urlToQuery,30 string attributeToFetch,31 string agreedValue32 );3334 function createRequest (35 string memory _urlToQuery,36 string memory _attributeToFetch37 )38 public39 {40 uint lenght = requests.push(Request(currentId, _urlToQuery, _attributeToFetch, ""));41 Request storage r = requests[lenght-1];4243 // Hardcoded oracles address44 r.quorum[address(0x6c2339b46F41a06f09CA0051ddAD54D1e582bA77)] = 1;45 r.quorum[address(0xb5346CF224c02186606e5f89EACC21eC25398077)] = 1;46 r.quorum[address(0xa2997F1CA363D11a0a35bB1Ac0Ff7849bc13e914)] = 1;4748 // launch an event to be detected by oracle outside of blockchain49 emit NewRequest (50 currentId,51 _urlToQuery,52 _attributeToFetch53 );5455 // increase request id56 currentId++;57 }5859 //called by the oracle to record its answer60 function updateRequest (61 uint _id,62 string memory _valueRetrieved63 ) public {6465 Request storage currRequest = requests[_id];6667 //check if oracle is in the list of trusted oracles68 //and if the oracle hasn't voted yet69 if(currRequest.quorum[address(msg.sender)] == 1){7071 //marking that this address has voted72 currRequest.quorum[msg.sender] = 2;7374 //iterate through "array" of answers until a position if free and save the retrieved value75 uint tmpI = 0;76 bool found = false;77 while(!found) {78 //find first empty slot79 if(bytes(currRequest.anwers[tmpI]).length == 0){80 found = true;81 currRequest.anwers[tmpI] = _valueRetrieved;82 }83 tmpI++;84 }8586 uint currentQuorum = 0;8788 //iterate through oracle list and check if enough oracles(minimum quorum)89 //have voted the same answer has the current one90 for(uint i = 0; i < totalOracleCount; i++){91 bytes memory a = bytes(currRequest.anwers[i]);92 bytes memory b = bytes(_valueRetrieved);9394 if(keccak256(a) == keccak256(b)){95 currentQuorum++;96 if(currentQuorum >= minQuorum){97 currRequest.agreedValue = _valueRetrieved;98 emit UpdatedRequest (99 currRequest.id,100 currRequest.urlToQuery,101 currRequest.attributeToFetch,102 currRequest.agreedValue103 );104 }105 }106 }107 }108 }109}110111Text112Xpath: /pre[2]/code113Afficher toutCopier
Nous aimerions avoir plus de documentation sur la création d'un contrat intelligent oracle. Si vous pouvez nous aider, créez une PR !
Complément d'information
- Decentralised Oracles: a comprehensive overview - Julien Thevenard
- Implementing a Blockchain Oracle on Ethereum - Pedro Costa
- Oracles - EthHub
Aidez-nous avec cette page
Si vous êtes un expert sur le sujet et que vous souhaitez contribuer, modifiez cette page et enrichissez-la de votre sagesse.
Vous serez crédité et vous aiderez la communauté Ethereum !
Utilisez la flexibilité de ce Modèle de documentation
Des questions ? Demandez-nous dans le salon #content de notre Serveur Discord
Modifier la page