NEW

Chainlink Data Streams have officially launched on mainnet. Sign up for early access.

Back

Feed Registry

The Chainlink Feed Registry is an onchain mapping of assets to feeds. It enables you to query Chainlink data feeds from asset addresses directly, without needing to know the feed contract addresses. They enable smart contracts to get the latest price of an asset in a single call, from a single contract.

For a complete list of functions and parameters for the FeedRegistryInterface contract, see the Feed Registry API Reference.

Base and Quote

The Feed Registry fully supports the AggregatorV3Interface API for multiple feeds. It maps feeds from base and quote address pairs. To get the latest LINK / USD round data from the registry, call:

latestRoundData(address base, address quote)

For example, to get the latest LINK / USD price:

  • base: The LINK token address on that network e.g. 0x514910771AF9Ca656af840dff83E8264EcF986CA for LINK on Ethereum mainnet
  • quote: A Denominations.USD address (0x0000000000000000000000000000000000000348), which is based on ISO 4217.
latestRoundData(0x514910771AF9Ca656af840dff83E8264EcF986CA, 0x0000000000000000000000000000000000000348)

To get the latest LINK / ETH price on Ethereum:

  • base: The LINK token address on that network e.g. 0x514910771AF9Ca656af840dff83E8264EcF986CA for LINK on Ethereum mainnet
  • quote: A Denominations.ETH address (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
latestRoundData(0x514910771AF9Ca656af840dff83E8264EcF986CA, 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)

Denominations library

A Denominations Solidity library is available for you to fetch currency identifiers which lack a canonical Ethereum address:

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

library Denominations {
    address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
    address public constant BTC = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;

    // Fiat currencies follow https://en.wikipedia.org/wiki/ISO_4217
    address public constant USD = address(840);
    address public constant GBP = address(826);
    address public constant EUR = address(978);

    // ... other fiat currencies
}

Code Examples

Solidity

To consume price data from the Feed Registry, your smart contract should reference FeedRegistryInterface, which defines the external functions implemented by the Feed Registry.

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

import {FeedRegistryInterface} from "@chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol";
import {Denominations} from "@chainlink/contracts/src/v0.8/Denominations.sol";

/**
 * 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 PriceConsumer {
    FeedRegistryInterface internal registry;

    /**
     * Network: Ethereum Mainnet
     * Feed Registry: 0x47Fb2585D2C56Fe188D0E6ec628a38b74fCeeeDf
     */
    constructor(address _registry) {
        registry = FeedRegistryInterface(_registry);
    }

    /**
     * Returns the ETH / USD price
     */
    function getEthUsdPrice() public view returns (int) {
        // prettier-ignore
        (
            /*uint80 roundID*/,
            int price,
            /*uint startedAt*/,
            /*uint timeStamp*/,
            /*uint80 answeredInRound*/
        ) = registry.latestRoundData(Denominations.ETH, Denominations.USD);
        return price;
    }

    /**
     * Returns the latest price
     */
    function getPrice(address base, address quote) public view returns (int) {
        // prettier-ignore
        (
            /*uint80 roundID*/,
            int price,
            /*uint startedAt*/,
            /*uint timeStamp*/,
            /*uint80 answeredInRound*/
        ) = registry.latestRoundData(base, quote);
        return price;
    }
}

Solidity Hardhat Example

Javascript

/**
 * 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.
 */

const web3 = new Web3("https://rpc.ankr.com/eth")
const feedRegistryInterfaceABI = [
  {
    anonymous: false,
    inputs: [
      { indexed: true, internalType: "address", name: "accessController", type: "address" },
      { indexed: true, internalType: "address", name: "sender", type: "address" },
    ],
    name: "AccessControllerSet",
    type: "event",
  },
  {
    anonymous: false,
    inputs: [
      { indexed: true, internalType: "address", name: "asset", type: "address" },
      { indexed: true, internalType: "address", name: "denomination", type: "address" },
      { indexed: true, internalType: "address", name: "latestAggregator", type: "address" },
      { indexed: false, internalType: "address", name: "previousAggregator", type: "address" },
      { indexed: false, internalType: "uint16", name: "nextPhaseId", type: "uint16" },
      { indexed: false, internalType: "address", name: "sender", type: "address" },
    ],
    name: "FeedConfirmed",
    type: "event",
  },
  {
    anonymous: false,
    inputs: [
      { indexed: true, internalType: "address", name: "asset", type: "address" },
      { indexed: true, internalType: "address", name: "denomination", type: "address" },
      { indexed: true, internalType: "address", name: "proposedAggregator", type: "address" },
      { indexed: false, internalType: "address", name: "currentAggregator", type: "address" },
      { indexed: false, internalType: "address", name: "sender", type: "address" },
    ],
    name: "FeedProposed",
    type: "event",
  },
  {
    anonymous: false,
    inputs: [
      { indexed: true, internalType: "address", name: "from", type: "address" },
      { indexed: true, internalType: "address", name: "to", type: "address" },
    ],
    name: "OwnershipTransferRequested",
    type: "event",
  },
  {
    anonymous: false,
    inputs: [
      { indexed: true, internalType: "address", name: "from", type: "address" },
      { indexed: true, internalType: "address", name: "to", type: "address" },
    ],
    name: "OwnershipTransferred",
    type: "event",
  },
  { inputs: [], name: "acceptOwnership", outputs: [], stateMutability: "nonpayable", type: "function" },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "address", name: "aggregator", type: "address" },
    ],
    name: "confirmFeed",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "decimals",
    outputs: [{ internalType: "uint8", name: "", type: "uint8" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "description",
    outputs: [{ internalType: "string", name: "", type: "string" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [],
    name: "getAccessController",
    outputs: [{ internalType: "contract AccessControllerInterface", name: "", type: "address" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint256", name: "roundId", type: "uint256" },
    ],
    name: "getAnswer",
    outputs: [{ internalType: "int256", name: "answer", type: "int256" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "getCurrentPhaseId",
    outputs: [{ internalType: "uint16", name: "currentPhaseId", type: "uint16" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "getFeed",
    outputs: [{ internalType: "contract AggregatorV2V3Interface", name: "aggregator", type: "address" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint80", name: "roundId", type: "uint80" },
    ],
    name: "getNextRoundId",
    outputs: [{ internalType: "uint80", name: "nextRoundId", type: "uint80" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint16", name: "phaseId", type: "uint16" },
    ],
    name: "getPhase",
    outputs: [
      {
        components: [
          { internalType: "uint16", name: "phaseId", type: "uint16" },
          { internalType: "uint80", name: "startingAggregatorRoundId", type: "uint80" },
          { internalType: "uint80", name: "endingAggregatorRoundId", type: "uint80" },
        ],
        internalType: "struct FeedRegistryInterface.Phase",
        name: "phase",
        type: "tuple",
      },
    ],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint16", name: "phaseId", type: "uint16" },
    ],
    name: "getPhaseFeed",
    outputs: [{ internalType: "contract AggregatorV2V3Interface", name: "aggregator", type: "address" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint16", name: "phaseId", type: "uint16" },
    ],
    name: "getPhaseRange",
    outputs: [
      { internalType: "uint80", name: "startingRoundId", type: "uint80" },
      { internalType: "uint80", name: "endingRoundId", type: "uint80" },
    ],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint80", name: "roundId", type: "uint80" },
    ],
    name: "getPreviousRoundId",
    outputs: [{ internalType: "uint80", name: "previousRoundId", type: "uint80" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "getProposedFeed",
    outputs: [{ internalType: "contract AggregatorV2V3Interface", name: "proposedAggregator", type: "address" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { 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: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint80", name: "roundId", type: "uint80" },
    ],
    name: "getRoundFeed",
    outputs: [{ internalType: "contract AggregatorV2V3Interface", name: "aggregator", type: "address" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint256", name: "roundId", type: "uint256" },
    ],
    name: "getTimestamp",
    outputs: [{ internalType: "uint256", name: "timestamp", type: "uint256" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [{ internalType: "address", name: "aggregator", type: "address" }],
    name: "isFeedEnabled",
    outputs: [{ internalType: "bool", name: "", type: "bool" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "latestAnswer",
    outputs: [{ internalType: "int256", name: "answer", type: "int256" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "latestRound",
    outputs: [{ internalType: "uint256", name: "roundId", type: "uint256" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    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: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "latestTimestamp",
    outputs: [{ internalType: "uint256", name: "timestamp", type: "uint256" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [],
    name: "owner",
    outputs: [{ internalType: "address", name: "", type: "address" }],
    stateMutability: "view",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "address", name: "aggregator", type: "address" },
    ],
    name: "proposeFeed",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
      { internalType: "uint80", name: "roundId", type: "uint80" },
    ],
    name: "proposedGetRoundData",
    outputs: [
      { internalType: "uint80", name: "id", 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: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "proposedLatestRoundData",
    outputs: [
      { internalType: "uint80", name: "id", 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: [{ internalType: "contract AccessControllerInterface", name: "_accessController", type: "address" }],
    name: "setAccessController",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
  },
  {
    inputs: [{ internalType: "address", name: "to", type: "address" }],
    name: "transferOwnership",
    outputs: [],
    stateMutability: "nonpayable",
    type: "function",
  },
  {
    inputs: [],
    name: "typeAndVersion",
    outputs: [{ internalType: "string", name: "", type: "string" }],
    stateMutability: "pure",
    type: "function",
  },
  {
    inputs: [
      { internalType: "address", name: "base", type: "address" },
      { internalType: "address", name: "quote", type: "address" },
    ],
    name: "version",
    outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
    stateMutability: "view",
    type: "function",
  },
]
const addr = "0x47Fb2585D2C56Fe188D0E6ec628a38b74fCeeeDf"
const feedRegistry = new web3.eth.Contract(feedRegistryInterfaceABI, addr)
const LINK = "0x514910771AF9Ca656af840dff83E8264EcF986CA"
const USD = "0x0000000000000000000000000000000000000348"

feedRegistry.methods
  .latestRoundData(LINK, USD)
  .call()
  .then((roundData) => {
    // Do something with roundData
    console.log("Latest Round Data", roundData)
  })

Latest Price

Contract Addresses

This section lists the blockchains that Chainlink Feed Registry are currently available on.

NetworkAddress
Ethereum Mainnet0x47Fb2585D2C56Fe188D0E6ec628a38b74fCeeeDf

What's next

Stay updated on the latest Chainlink news