Skip to main content

Getting Started

Scaling provides offchain access to anchor feeds, using Flare's network of 100 independent data providers and a full commit-reveal process every 90 seconds.

This section demonstrates how to consume anchor feeds on Flare. The key steps to read an anchor feed are:

  1. Fetch anchor feed data offchain:

    Query the Data Availability (DA) Layer to retrieve anchor feeds along with cryptographic proofs.

  2. Verify the proof onchain:

    Validate the proof provided by the DA Layer onchain, ensuring it matches the finalized version recorded by Scaling.

  3. Use the feed data onchain:

    After verification, integrate the feed data into your onchain application logic.

Scaling only stores commitments to feed data onchain. The complete feed data resides offchain but can be verified onchain against a Merkle root. This ensures data integrity and guards against tampering.

DA Layer API URLs

Rate limits

The public DA Layer endpoints are rate-limited. To request an API key for higher limits, create an API Key Request Issue.

The DA Layer provides a set of API endpoints for querying offchain data from Flare protocols.

NetworkBase URLAPI Reference
Flare Mainnethttps://flr-data-availability.flare.network/Reference
Songbird Canary-Networkhttps://sgb-data-availability.flare.network/Reference

Fetching anchor feed data

The DA Layer API allows querying the value and proof for multiple feeds from the same voting epoch in a single request. Use the anchor-feeds-with-proof POST endpoint to retrieve pricing data.

For example, to get the feed value of FLR/USD, BTC/USD and ETH/USD at the latest voting round:

curl -X 'POST' \
'https://flr-data-availability.flare.network/api/v0/ftso/anchor-feeds-with-proof' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"feed_ids": [
"0x01464c522f55534400000000000000000000000000",
"0x014254432f55534400000000000000000000000000",
"0x014554482f55534400000000000000000000000000"
]
}'

API Response

The response contains JSON objects for each feed, with the following fields:

  • votingRoundId: ID of the current voting round, each lasting 90s (see the Flare Systems Explorer).
  • id: ID of the feed (see list of anchor feeds).
  • value: Integer value of the feed.
  • turnoutBIPS: Percentage (in basis points) of voting weight which contributed towards the finalized value.
  • decimals: Number of decimal places for the feed.
  • proof: Merkle proof array for data verification.

An example response for BTC/USD:

[
{
"body": {
"votingRoundId": 823386,
"id": "0x014254432f55534400000000000000000000000000",
"value": 9837867,
"turnoutBIPS": 9442,
"decimals": 2
},
"proof": [
"0x79b8a56bf66ae571ed4c0e3e1317825277c43f5ca3b5a85b834fb6407de03b63",
"...additional proof hashes..."
]
}
]

The floating point value of a feed can be calculated by dividing the value by 10^decimals. For example, if the feed value of BTC/USD is 6900420 and the decimal is 2, the floating point feed value is 69004.20.

Verifying proof onchain

To verify feed data onchain, use the FtsoV2Interface. This interface offers the verifyFeedData method to validate feed data and proof against the onchain Merkle root. The function requires a single input struct FeedDataWithProof, which includes the feed data and voting round ID within the FeedData struct, and a Merkle proof.

An example contract verifying and consuming anchor feeds onchain

FtsoV2AnchorFeedConsumer.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import {FtsoV2Interface} from "@flarenetwork/flare-periphery-contracts/coston2/FtsoV2Interface.sol";
import {ContractRegistry} from "@flarenetwork/flare-periphery-contracts/coston2/ContractRegistry.sol";

/**
* THIS IS AN EXAMPLE CONTRACT.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
contract FtsoV2AnchorFeedConsumer {
mapping(uint32 => mapping(bytes21 => FtsoV2Interface.FeedData))
public provenFeeds;

function savePrice(FtsoV2Interface.FeedDataWithProof calldata data) public {
// Step 1: Verify the proof
require(
ContractRegistry.getFtsoV2().verifyFeedData(data),
"Invalid proof"
);
// Step 2: Use the feed data with app specific logic
// Here the feeds are saved
provenFeeds[data.body.votingRoundId][data.body.id] = data.body;
}
}

Fetching and verifying feeds

The following example shows how to query feed and proof data from DA Layer and submit it to the onchain consumer:

fetch_and_verify_anchor_onchain.js
// THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.
import { artifacts } from "hardhat";
import { fetchAnchorFeeds } from "./fetch_anchor_feeds";

const FtsoV2AnchorFeedConsumer = artifacts.require(
"FtsoV2AnchorFeedConsumer.sol",
);

// Feed IDs, see https://dev.flare.network/ftso/scaling/anchor-feeds for full list
const BTC_USD_FEED_ID = "0x014254432f55534400000000000000000000000000";
const TARGET_VOTING_ROUND = 823402;

async function main() {
// Deploy FtsoV2AnchorFeedConsumer contract
const feedConsumer = await FtsoV2AnchorFeedConsumer.new();

// Fetch price from DA Layer
const feedData = await fetchAnchorFeeds(
[BTC_USD_FEED_ID],
TARGET_VOTING_ROUND,
);

// Save fetched price to contract
await feedConsumer.savePrice({
proof: feedData[0].proof,
body: feedData[0].data,
});

// Query saved price from contract
const savedPrice = await feedConsumer.provenFeeds.call(
TARGET_VOTING_ROUND,
BTC_USD_FEED_ID,
);
const formattedPrice = savedPrice.value * Math.pow(10, -savedPrice.decimals);
console.log(
`Saved price: ${formattedPrice} USD at voting round: ${savedPrice.votingRoundId.toString()}`,
);
}

main();