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
Currency | Address |
---|---|
USD | 0x0000000000000000000000000000000000000840 |
Feed registry address (X Layer mainnet)#
Network | Feed registry address |
---|---|
X Layer mainnet | 0xfe3240995c771f10D2583e8fa95F92ee40E15150 |
Feed adapter address (X Layer mainnet)#
Network | Deviation threshold | Heartbeat | Feed adapter address |
---|---|---|---|
WBTC/USD | 0.5% | 3600s | 0x3C7dCE5F83E99452CD399a1bCa5542BEd979E6CA |
WETH/USD | 0.5% | 3600s | 0x98ff91433c992153A8D6507cEA5b791Df69d7c99 |
OKB/USD | 0.5% | 3600s | 0x90AB4bc4991c71889A67F25eec044fD90E255e77 |
USDT/USD | 0.5% | 3600s | 0xB249978EfdB8E01D5266F926409870c1Ec7336EA |
USDC/USD | 0.5% | 3600s | 0xc975719d0ec39bb8880444acea9cc8d29a35e4d4 |
DAI/USD | 0.5% | 3600s | 0x960cF115eeEAFBF5B184070DE9eD89593c712B71 |
Feed registry address (X Layer testnet)#
Network | Feed registry address |
---|---|
X Layer testnet | 0x038969dD2036270c22D9F5ABE840cd5CDC079848 |
Feed adapter address (X Layer testnet)#
Network | Deviation threshold | Heartbeat | Feed adapter address |
---|---|---|---|
WBTC/USD | 0.5% | 3600s | 0x03e29fb6dbb5e0600ad062e5f80cf50e651571b3 |
WETH/USD | 0.5% | 3600s | 0x258b77b31dF0eF3C2F1495152b81e305bD83Aab8 |
OKB/USD | 0.5% | 3600s | 0x92ac502FC54356868C4EAc1B2eF0f941C2895dd0 |
USDT/USD | 0.5% | 3600s | 0xA774557280A45E4433a1208f6E5c0dA718a84b7C |
USDC/USD | 0.5% | 3600s | 0xa8f52bbb506E0bD05253e007A46f6A1d8a4000cf |
DAI/USD | 0.5% | 3600s | 0x185919669101D4748423B3Ce7C07A0207e6d99e8 |