Chainlink Oracles: A Help Guide

Kerala Blockchain Academy
6 min readNov 9, 2023

By Lekshmi Pg, Research Engineer, Kerala Blockchain Academy

Chainlink is a decentralised computing platform that provides many Blockchain solutions like Decentralized Oracles, CCIP (Cross-Chain Interoperability Protocol), VRF generators, etc. So here we will concentrate on one of the services Chainlink provides, i.e., Oracle service.

As you may know, Blockchain uses the Oracle service for getting real-time information from outside the Blockchain network. You can go through this medium content if you are unfamiliar with Oracle Concept. So Chainlink is one such, or can say commonly used Oracle service.

Chainlink populates the blockchain world with so many data feeds, like

Price Feeds: get the real-world price of different cryptocurrencies & tokens like BTC, ETH, 1Inch, etc.

NFT Floor Price Feeds: provide a cautious and prudent minimum valuation for NFT collections.

Rate and Volatility Feeds: provide data for cryptos’ interest rates and asset volatility.

L2 Sequencer Uptime Feeds: Providing more L2 sequencers and thereby supporting L2s.

Proof of Reserve Feeds: provide the status of reserves of several on-chain and off-chain assets.

Let’s demonstrate Chainlink’s oracle service with the help of an example.

Let’s take the case of Ameya, who is running a DeFi Service. For running the DeFi Service, Live updates on token prices are necessary. Since it’s a DeFi, smart contracts manage everything, and as you know, smart contracts cannot directly call or interact with an API to get real-world data. So, she can assign a person here to give the data directly to the smart contract or call an API from the backend and give data to the smart contract. But in both cases, decentralisation is compromised; how? In both cases, the application trusts a single person or API, which is controversial while running an app in a web3 world.

So here comes Decentralized Oracle Network(DON) for help. You can read on DON here. So, a few companies provide these DON services; the most prominent among them is Chainlink. Chainlink does this by deploying Oracle contracts on-chain and publishing the deployed address so that any smart contract can use it.

Chainlink is maintaining the Oracle Contract and developed an Interface contract for seamless interaction with the Oracle contract. Chainlink deploys both contracts on the most prominent blockchains, including Testnets, and publishes the contract addresses on their official websites. When we want to retrieve a data feed from Chainlink, the best practice is to use an Interface of Chainlink to communicate with the main contract.

In our case, for getting the price data, we have a reference contract called AccessControlledOffchainAggregator, where the data feeds are updated at regular intervals. Let’s call this contract Aggregator Contract. You can directly interact with the Aggregator contract. But the best practice is to interact with the Aggregator contract through Interface so that changes happening on the Aggregator contract won’t affect your code. The AggregatorV3Interface is the interface contract. Chainlink had deployed these contracts on the most prominent blockchains, including Testnets, and also published the contract addresses on their sites.

So, let’s solve Ameya’s problem using the Chainlink Oracle service to get the real-time price of ETH in USD. So, what Ameya can do is interact with Chainlink’s Oracle Contract through an interface. Here is the contract, which is written to get the price value of ETH in USD. Here, we will deploy it in Sepolia to check it’s working.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract PriceConsumerV3 {

AggregatorV3Interface internal priceFeed;

/* Initializing Interface Object */
constructor() {
priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);
}

/* Getting RealTime data */
function getLatestPrice() public view returns (int) {
(
/*uint80 roundID*/,
int price,
/*uint startedAt*/,
/*uint timeStamp*/,
/*uint80 answeredInRound*/
) = priceFeed.latestRoundData();
return price;
}
}

Let’s break the code & explain…

Here, PriceConsumerV3 is the contract collecting data feeds relating to the value of ETH in USD. Here, we are using AggregatorV3Interface to interact with the Aggregator contract. For that, she needs to import the AggregatorV3Interface contract. After that, create an object of this Interface contract to interact with it.

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract PriceConsumerV3 {

AggregatorV3Interface internal priceFeed;

For directly interacting with the Interface contract, she needs to initialise the object using the Interface Contract address. So, how can she get the contract address??? Getting the contract address is as easy as fixing a tie; I’m just joking. As said earlier, Chainlink published all the contract addresses on the site. Just go there and get it.

As said earlier, we will deploy it in Sepolia Testnet, so go to the chainlink site and get the contract address of AggregatorV3Interface deployed on Sepolia. Using the address, the Interface Object was initialised.

constructor() {
priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);
}

Here, initialising is done inside the constructor just to do the initialisation at the time of deployment.

After that, there is a function, getLatestPrice(), to get the latest price. In this function, we are directly calling the latestRoundData() function of AggregatorV3Interface. Here, this function returns multiple results like roundId, price(answer), startedAt, updatedAt, and answeredInRound(Deprecated).

Before explaining each of this, lets look into what is a Round in chainlink oracle contracts. As you know oracles periodically updates the reference or aggregator contract. And each Round is identified using RoundID. This RoundID is important since the value of each Round may differ due to real-time variations, if we want to do any verification after some period of time, we have to get the value from that particular RoundID

Coming back to the return values of latestRoundData():

  • roundID: the roundID of that particular Round
  • price(answer): here is the field where we get the answer to the question. So, in our case, is the price data
  • startedAt: Timestamp denotes the starting of this Round
  • updatedAt: Timestamp denotes updation of Round
  • answerInRound(): this parameter is deprecated, actually used when an answer needs multiple rounds of computation

In this case, need only the price(answer) parameter, so the contract specifies only the price parameter.

function getLatestPrice() public view returns (int) {
(
/*uint80 roundID*/,
int price,
/*uint startedAt*/,
/*uint timeStamp*/,
/*uint80 answeredInRound*/
) = priceFeed.latestRoundData();
return price;
}

Here, the getLatestPrice( ) function returns the price, which is the actual thing Ameya wants for her DeFi service. Ameya’s problem solved…Thanks to Oracle & Chainlink.

Let’s move forward by deploying the contract using Remix in Sepolia.

So, we will get a tab in Remix through which we can interact with the contract.

Here, we can give a call to getLatestPrice function and get the real-time price of ETH in USD.

price as of 20/10/2023

So here we are, getting the result in int256. So now Ameya can make the necessary conversions and use the value for her truly decentralised finance.

Would you like to try out the Oracle Service using this code? Check out the smart contract << 0xb744Ef6c4f140d8977651cA4DD30860883F0A098>> on Sepolia testnet.

References

[1] https://ethereum.org/he/developers/docs/

[2] https://chain.link/

[3] https://medium.com/blockchain-stories/defi-lending-and-borrowing-272d1f2b87de

[4] https://medium.com/@kbaiiitmk/interacting-with-an-ethereum-node-using-apis-eab75cb1fbe4

--

--

Kerala Blockchain Academy

One-stop solution for quality blockchain education and research. Offers best in class blockchain certification programs in multiple blockchain domains.