Oracle
Price feed

Price feed#

You can use X Layer data feeds to connect your smart contracts to asset pricing data such as the BTC/USD. These data feeds use data aggregated from many independent data sources. Each price feed has an onchain address and functions that enable contracts to read pricing data from that address.

Using data feeds#

The code for reading Data Feeds is the same across all EVM-compatible blockchains and Data Feed types. You choose different types of feeds for different uses, but the request and response format are the same. To read a feed, specify the following variables:

  • RPC endpoint URL: This determines which network that your smart contracts will run on. You can use a node provider service or point to your own client. If you are using a Web3 wallet, it is already configured with the RPC endpoints for several networks and the Remix IDE will automatically detect them for you.
  • Price feed contract address: This determines which data feed your smart contract will read on X Layer mainnet or testnet. The examples in this document indicate these variables, but you can modify the examples to work on different networks and read different feeds.

The following guide will show an example that reads data feeds using the following languages:

  • Onchain consumer contracts:
    • Solidity
    • Vyper

Reading data feeds onchain#

These code examples demonstrate how to deploy a consumer contract onchain that reads a data feed and stores the value.

Solidity#

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.20;

/**
 * Aggregator Interface that is compatible with Chainlink's AggregatorV3Interface
 */
interface AggregatorV3Interface {
    function decimals() external view returns (uint8);

    function description() external view returns (string memory);

    function version() external view returns (uint256);

    function getRoundData(
        uint80 _roundId
    )
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );

    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
}

contract DataConsumer {
    AggregatorV3Interface internal dataFeed;

    /**
     * Network: XLayer Testnet
     * Aggregator: WBTC/USD
     * Address: 0x03e29FB6DBb5e0600AD062e5F80Cf50e651571B3
     */

    constructor() {
        dataFeed = AggregatorV3Interface(
            0x03e29FB6DBb5e0600AD062e5F80Cf50e651571B3
        );
    }

    function getWbtcFeedLatestAnswer() public view returns (int256) {
        // prettier-ignore
        (
            /* uint80 roundID */,
            int answer,
            /*uint startedAt*/,
            /*uint timeStamp*/,
            /*uint80 answeredInRound*/
        ) = dataFeed.latestRoundData();
        return answer;
    }
}

Vyper#

To use the price data, your smart contract should import AggregatorV3Interface which defines the external functions implemented by data feeds. You can find it here. You can also find a PriceConsumer example here. Read the apeworx-starter-kit README to learn how to run the example code.

Using feed registry#

The feed registry is an onchain mapping of assets to feeds. It enables you to query 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, see the Feed Registry API Reference.

Code example#

Solidity#

To use the 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.20;

interface IFeedRegistry {
    // V3 AggregatorV3Interface
    function decimals(
        address base,
        address quote
    ) external view returns (uint8);

    function description(
        address base,
        address quote
    ) external view returns (string memory);

    function version(
        address base,
        address quote
    ) external view returns (uint256);

    function latestRoundData(
        address base,
        address quote
    )
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );

    function getRoundData(
        address base,
        address quote,
        uint80 _roundId
    )
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
}

contract PriceConsumer {
    IFeedRegistry internal registry;
    /**
     * Following fiat currency standards of https://en.wikipedia.org/wiki/ISO_4217
     */
    address internal constant USD = address(840);
    address internal constant WETH = 0x5A77f1443D16ee5761d310e38b62f77f726bC71c;

    /**
     * Network: XLayer Mainnet
     * Feed Registry: 0xfe3240995c771f10D2583e8fa95F92ee40E15150
     * WETH: 0x5A77f1443D16ee5761d310e38b62f77f726bC71c
     */
    constructor() {
        registry = IFeedRegistry(0xfe3240995c771f10D2583e8fa95F92ee40E15150);
    }

    /**
     * Returns the WETH / USD price
     */
    function getWethUsdPrice() public view returns (int256) {
        // prettier-ignore
        (
            /*uint80 roundID*/,
            int price,
            /*uint startedAt*/,
            /*uint timeStamp*/,
            /*uint80 answeredInRound*/
        ) = registry.latestRoundData(WETH, 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;
    }
}

Price feed contract addresses#

To ensure accurate data is fed to the smart contracts in a timely manner, X Layer oracle will feed the price to the smart contracts in regards to two parameters: deviation threshold and heartbeat threshold:

  • Deviation threshold: The deviation of crypto price data beyond a certain interval triggers smart contracts to update.
  • Heartbeat threshold: If the data values stay within the deviation parameters, it will only trigger an update every x minute.

Fiat currency standard#

Fiat currencies lack a canonical EVM address on-chain, and are configured on X Layer to maintain the following standard

CurrencyAddress
USD0x0000000000000000000000000000000000000840

Feed registry address (X Layer mainnet)#

NetworkFeed registry address
X Layer mainnet0xfe3240995c771f10D2583e8fa95F92ee40E15150

Feed adapter address (X Layer mainnet)#

NetworkDeviation thresholdHeartbeatFeed adapter address
WBTC/USD0.5%3600s0x3C7dCE5F83E99452CD399a1bCa5542BEd979E6CA
WETH/USD0.5%3600s0x98ff91433c992153A8D6507cEA5b791Df69d7c99
OKB/USD0.5%3600s0x90AB4bc4991c71889A67F25eec044fD90E255e77
USDT/USD0.5%3600s0xB249978EfdB8E01D5266F926409870c1Ec7336EA
USDC/USD0.5%3600s0xc975719d0ec39bb8880444acea9cc8d29a35e4d4
DAI/USD0.5%3600s0x960cF115eeEAFBF5B184070DE9eD89593c712B71

Feed registry address (X Layer testnet)#

NetworkFeed registry address
X Layer testnet0x038969dD2036270c22D9F5ABE840cd5CDC079848

Feed adapter address (X Layer mainnet)#

NetworkDeviation thresholdHeartbeatFeed adapter address
WBTC/USD0.5%3600s0x03e29fb6dbb5e0600ad062e5f80cf50e651571b3
WETH/USD0.5%3600s0x258b77b31dF0eF3C2F1495152b81e305bD83Aab8
OKB/USD0.5%3600s0x92ac502FC54356868C4EAc1B2eF0f941C2895dd0
USDT/USD0.5%3600s0xA774557280A45E4433a1208f6E5c0dA718a84b7C
USDC/USD0.5%3600s0xa8f52bbb506E0bD05253e007A46f6A1d8a4000cf
DAI/USD0.5%3600s0x185919669101D4748423B3Ce7C07A0207e6d99e8