Search
Chainlink Data Feeds are the quickest way to connect your smart contracts to the real-world market prices of assets. For example, one use for data feeds is to enable smart contracts to retrieve the latest pricing data of an asset in a single call.
This guide applies specifically to using data feeds on EVM Chains. To get the full list of Chainlink Data Feeds running on the EVM Chains, see the Reference Contracts page.
Select quality data feeds
Be aware of the quality of the data that you use. Learn more about making responsible data quality decisions.
For important updates regarding the use of Chainlink Price Feeds, users should join the official Chainlink Discord and subscribe to the data-feeds-user-notifications channel: https://discord.gg/Dqy5N9UbsR
You can use smart contracts to get asset prices on EVM Chains. These examples show you how to get the price of Ethereum (ETH) on the Ethereum network, but you can modify the examples to work on other EVM Chains as well. The list of data feeds for each network are available on the Data Feed Contracts page. For development, use testnet data feeds such as the BTC / USD feed on the Goerli testnet.
You can write smart contracts that consume data feeds using several languages, but this guide shows you the following examples:
To consume price data, your smart contract should reference AggregatorV3Interface
, which defines the external functions implemented by Data Feeds.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract PriceConsumerV3 {
AggregatorV3Interface internal priceFeed;
/**
* Network: Goerli
* Aggregator: ETH/USD
* Address: 0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
*/
constructor() {
priceFeed = AggregatorV3Interface(0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e);
}
/**
* Returns the latest price
*/
function getLatestPrice() public view returns (int) {
(
/*uint80 roundID*/,
int price,
/*uint startedAt*/,
/*uint timeStamp*/,
/*uint80 answeredInRound*/
) = priceFeed.latestRoundData();
return price;
}
}
The latestRoundData
function returns five values representing information about the latest price data. See the Data Feeds API Reference for more details.
To consume price data, your smart contract should import AggregatorV3Interface
which defines the external functions implemented by Data Feeds. You can find it here.
You can find a PriceConsumer
example here. Read the apeworx-starter-kit README to learn how to run the example.
This example uses web3.js to retrieve feed data from the BTC / USD feed on the Goerli testnet.
/**
* THIS IS EXAMPLE CODE THAT USES HARDCODED VALUES FOR CLARITY.
* THIS IS EXAMPLE CODE THAT USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
const Web3 = require("web3") // for nodejs only
const web3 = new Web3("https://rpc.ankr.com/eth_goerli")
const aggregatorV3InterfaceABI = [{ "inputs": [], "name": "decimals", "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "description", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint80", "name": "_roundId", "type": "uint80" }], "name": "getRoundData", "outputs": [{ "internalType": "uint80", "name": "roundId", "type": "uint80" }, { "internalType": "int256", "name": "answer", "type": "int256" }, { "internalType": "uint256", "name": "startedAt", "type": "uint256" }, { "internalType": "uint256", "name": "updatedAt", "type": "uint256" }, { "internalType": "uint80", "name": "answeredInRound", "type": "uint80" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "latestRoundData", "outputs": [{ "internalType": "uint80", "name": "roundId", "type": "uint80" }, { "internalType": "int256", "name": "answer", "type": "int256" }, { "internalType": "uint256", "name": "startedAt", "type": "uint256" }, { "internalType": "uint256", "name": "updatedAt", "type": "uint256" }, { "internalType": "uint80", "name": "answeredInRound", "type": "uint80" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "version", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }]
const addr = "0xA39434A63A52E749F02807ae27335515BA4b07F7"
const priceFeed = new web3.eth.Contract(aggregatorV3InterfaceABI, addr)
priceFeed.methods.latestRoundData().call()
.then((roundData) => {
// Do something with roundData
console.log("Latest Round Data", roundData)
})
/**
* THIS IS EXAMPLE CODE THAT USES HARDCODED VALUES FOR CLARITY.
* THIS IS EXAMPLE CODE THAT USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
const { ethers } = require("ethers") // for nodejs only
const provider = new ethers.providers.JsonRpcProvider("https://rpc.ankr.com/eth_goerli")
const aggregatorV3InterfaceABI = [{ "inputs": [], "name": "decimals", "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "description", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "uint80", "name": "_roundId", "type": "uint80" }], "name": "getRoundData", "outputs": [{ "internalType": "uint80", "name": "roundId", "type": "uint80" }, { "internalType": "int256", "name": "answer", "type": "int256" }, { "internalType": "uint256", "name": "startedAt", "type": "uint256" }, { "internalType": "uint256", "name": "updatedAt", "type": "uint256" }, { "internalType": "uint80", "name": "answeredInRound", "type": "uint80" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "latestRoundData", "outputs": [{ "internalType": "uint80", "name": "roundId", "type": "uint80" }, { "internalType": "int256", "name": "answer", "type": "int256" }, { "internalType": "uint256", "name": "startedAt", "type": "uint256" }, { "internalType": "uint256", "name": "updatedAt", "type": "uint256" }, { "internalType": "uint80", "name": "answeredInRound", "type": "uint80" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "version", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }]
const addr = "0xA39434A63A52E749F02807ae27335515BA4b07F7"
const priceFeed = new ethers.Contract(addr, aggregatorV3InterfaceABI, provider)
priceFeed.latestRoundData()
.then((roundData) => {
// Do something with roundData
console.log("Latest Round Data", roundData)
})
This example uses Web3.py to retrieve feed data from the BTC / USD feed on the Goerli testnet.
# THIS IS EXAMPLE CODE THAT USES HARDCODED VALUES FOR CLARITY.
# THIS IS EXAMPLE CODE THAT USES UN-AUDITED CODE.
# DO NOT USE THIS CODE IN PRODUCTION.
from web3 import Web3
# Change this to use your own RPC URL
web3 = Web3(Web3.HTTPProvider('https://rpc.ankr.com/eth_goerli'))
# AggregatorV3Interface ABI
abi = '[{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint80","name":"_roundId","type":"uint80"}],"name":"getRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestRoundData","outputs":[{"internalType":"uint80","name":"roundId","type":"uint80"},{"internalType":"int256","name":"answer","type":"int256"},{"internalType":"uint256","name":"startedAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"},{"internalType":"uint80","name":"answeredInRound","type":"uint80"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]'
# Price Feed address
addr = '0xA39434A63A52E749F02807ae27335515BA4b07F7'
# Set up contract instance
contract = web3.eth.contract(address=addr, abi=abi)
# Make call to latestRoundData()
latestData = contract.functions.latestRoundData().call()
print(latestData)
You can find an example with all the source files here. This example uses go-ethereum to retrieve feed data from the BTC / USD feed on the Goerli testnet.
To learn how to run the example, see the README.
New Feed Registry
You can use the Feed Registry to reference data feed assets by name or currency identifier instead of by pair/proxy address.
Chainlink Data Feeds can be used in combination to derive denominated price pairs in other currencies.
If you require a denomination other than what is provided, you can use two data feeds to derive the pair that you need. For example, if you needed a BTC / EUR price, you could take the BTC / USD feed and the EUR / USD feed and derive BTC / EUR using division.
Important
If your contracts require Solidity versions that are >=0.6.0 <0.8.0
, use OpenZeppelin's SafeMath version 3.4.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
/**
* Network: Rinkeby (No Goerli Feed for EUR/USD at this time)
* Base: BTC/USD
* Base Address: 0xECe365B379E1dD183B20fc5f022230C044d51404
* Quote: EUR/USD
* Quote Address: 0x78F9e60608bF48a1155b4B2A5e31F32318a1d85F
* Decimals: 8
*/
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
contract PriceConverter {
function getDerivedPrice(address _base, address _quote, uint8 _decimals)
public
view
returns (int256)
{
require(_decimals > uint8(0) && _decimals <= uint8(18), "Invalid _decimals");
int256 decimals = int256(10 ** uint256(_decimals));
( , int256 basePrice, , , ) = AggregatorV3Interface(_base).latestRoundData();
uint8 baseDecimals = AggregatorV3Interface(_base).decimals();
basePrice = scalePrice(basePrice, baseDecimals, _decimals);
( , int256 quotePrice, , , ) = AggregatorV3Interface(_quote).latestRoundData();
uint8 quoteDecimals = AggregatorV3Interface(_quote).decimals();
quotePrice = scalePrice(quotePrice, quoteDecimals, _decimals);
return basePrice * decimals / quotePrice;
}
function scalePrice(int256 _price, uint8 _priceDecimals, uint8 _decimals)
internal
pure
returns (int256)
{
if (_priceDecimals < _decimals) {
return _price * int256(10 ** uint256(_decimals - _priceDecimals));
} else if (_priceDecimals > _decimals) {
return _price / int256(10 ** uint256(_priceDecimals - _decimals));
}
return _price;
}
}
Data Feeds are aggregated from many data sources by a decentralized set of independent Node Operators. The Decentralized Data Model describes this in detail.
Getting the latest price is not the only data that aggregators can retrieve. You can also retrieve historical price data. To learn more, see the Historical Price Data page.
To understand different use cases for Chainlink Price Feeds, refer to Other Tutorials.