Oracoli
Gli oracoli sono feed di dati che collegano Ethereum a informazioni del mondo reale esternamente alla catena, in modo da poter interrogare i dati negli Smart Contract. Ad esempio, le dapp dei mercati predittivi utilizzano gli oracoli per effettuare i pagamenti in base a eventi. Un mercato predittivo potrebbe chiedere di puntare ETH sul prossimo presidente degli Stati Uniti. Userà un oracolo per confermare l'esito e pagare i vincitori.
Prerequisiti
È necessario avere familiarità con nodi, meccanismi di consenso e anatomia degli Smart Contract, in particolare eventi.
Cos'è un oracolo
Un oracolo è un ponte tra la blockchain e il mondo reale. Agisce come API sulla catena, che è possibile interrogare per ottenere informazioni da inserire negli Smart Contract. Si può trattare di qualsiasi cosa, da informazioni sui prezzi a previsioni meteo.
Perché sono necessari?
Con una blockchain come Ethereum è necessario che ogni nodo della rete sia in grado di riprodurre ogni transazione e ottenere lo stesso risultato, garantito. Le API introducono dati potenzialmente variabili. Se hai inviato a qualcuno una quantità di ETH basata su un valore concordato in $USD utilizzando un'API per i prezzi, la query restituirà un risultato diverso ogni giorno. Per non parlare del fatto che l'API potrebbe venire compromessa o essere obsoleta. In tal caso, i nodi della rete non sarebbero in grado di concordare lo stato corrente di Ethereum e, di fatto, verrebbe meno il consenso.
Gli oracoli risolvono questo problema pubblicando i dati sulla blockchain. Quindi ogni nodo che riproduce la transazione utilizzerà gli stessi dati immutabili che vengono pubblicati affinché siano visibili a tutti. A questo scopo, un oracolo in genere è costituito da uno Smart Contract e da alcuni componenti esterni alla catena che possono interrogare le API e poi inviare periodicamente transazioni per aggiornare i dati dello Smart Contract.
Sicurezza
La sicurezza di un oracolo è pari a quella delle sue origini sue fonte(i) di dati. Se una dapp utilizza Uniswap come oracolo per il suo feed di prezzo ETH/DAI, è possibile per un aggressore spostare il prezzo su Uniswap al fine di manipolare la conoscenza della dapp del prezzo corrente. Un esempio per contrastare questa situazione ciò è un sistema di feed come quello usato da MakerDAO, che raccoglie i dati sui prezzi da una serie di feed di prezzo esterni anziché fare affidamento su una sola origine.
Utilizzo
Oracoli come servizio
Servizi come Chainlink offrono gli oracoli sotto forma di servizio. Hanno già l'infrastruttura, ad esempio, per:
- ricevere feed sul prezzo di una criptovaluta nel contratto
- generare numeri casuali verificabili (utili per il gioco)
- chiamare API esterne – un nuovo uso in questo senso è per controllare le riserve wBTC
Questo è un esempio di come ottenere il prezzo più aggiornato degli ETH in uno Smart Contract utilizzando un feed di prezzo Chainlink:
1pragma solidity ^0.6.7;23import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";45contract PriceConsumerV3 {67 AggregatorV3Interface internal priceFeed;89 /**10 * Network: Kovan11 * Aggregator: ETH/USD12 * Address: 0x9326BFA02ADD2366b30bacB125260Af64103133113 */14 constructor() public {15 priceFeed = AggregatorV3Interface(0x9326BFA02ADD2366b30bacB125260Af641031331);16 }1718 /**19 * Returns the latest price20 */21 function getLatestPrice() public view returns (int) {22 (23 uint80 roundID,24 int price,25 uint startedAt,26 uint timeStamp,27 uint80 answeredInRound28 ) = priceFeed.latestRoundData();29 return price;30 }31}32Mostra tuttoCopia
Servizi per oracoli
Creare uno Smart Contract oracolo
Ecco un esempio di contratto oracolo di Pedro Costa. Puoi trovare ulteriori commenti nel suo articolo: 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}110Mostra tuttoCopia
Ci piacerebbe avere più documentazione sulla creazione di uno Smart Contract oracolo. Se vuoi dare il tuo aiuto, crea una PR!
Letture consigliate
- Decentralised Oracles: a comprehensive overview –Julien Thevenard
- Implementing a Blockchain Oracle on Ethereum –Pedro Costa
- Oracles –EthHub
Aiutaci con questa pagina
Se conosci l'argomento e vuoi contribuire, modifica questa pagina e condividi un po' del tuo sapere.
Il tuo nome verrà aggiunto ai crediti e aiuterai la community di Ethereum!
Usa questo flessibile modello di documentazione
Domande? Chiedicelo nel canale #content sul nostro server Discord
Modifica pagina