Skip to content

Deploying a Price Provider#

Background#

Providing prices to the FTSO system makes you a part of a decentralized oracle system. FTSO price providers submit prices to on chain contracts deployed on the Songbird network. The main contracts a price provider will interact with are the price Submitter and the FTSO contracts. All the relevant contracts for the FTSO system are available on the smart contract repo (see the Developer Docs section). These contracts are deployed and verified on the songbird explorer.

Perquisites#

For operating a price provider. You will have to be familiar with:

  • smart contracts and Solidity.
  • interacting with smart contract using a web3 library.
  • hardhat runtime environment.

First steps#

To facilitate an easier start, one can use the kick-off NPM package referenced here. This package showcases the main contracts related to whitelisting a price provider and submitting prices. The package enables you to deploy FTSO mock contracts in a local setup, and submit prices to those contracts. Working with the package should help all setup stages for your price provider.

Working with this package package is mostly identical to providing on chain prices. Below aspects would be the same as working on chain:

  • smart contract APIs (called functions)
  • events.
  • timing aspects are similar but not identical.

The package does not cover the actual price calculation (weighted median) and rewarding as they occur on the real network.

Please visit the Developer Docs section to find a link to a reference implementation of a price provider. You can find useful ideas in this code that will help you interact with the FTSO contracts and the Flare chain. Do note you will have to do some work on top of this implementation if you would like to win rewards.

Providing Random numbers#

The price providing process is structured as a commit/reveal scheme to prevent users from copying submission data. The commit and reveal phases have strict time windows of a few minutes. With each reveal the price provider is also providing a random number. The random number is used as a salt in the reveal-commit scheme and later used in the reward calculation process.

Price providers are encouraged to provide strong cryptographically secure random numbers with high entropy and sufficient range. Strong random numbers are important for network security since this is the only true source of randomness on the network. Random numbers also make the commit-reveal scheme resilient to attacks. Random numbers below 2128 are considered unsafe and are rejected on reveal.

Going live#

Once you feel comfortable with the local NPM package, you are ready to start submitting your prices on chain.

For running on the real network you will have to face some new challenges:

  • Gain vote power - A price provider can only whitelist himself as a provider if they have enough vote power.
  • Observation node - It is recommended that each price provider runs an observation node.
  • Timing issues - you will face to challenges:
  • Align with the on chain time data - the on chain time stamp might skew up to 30-40 seconds from the real world time.
  • Figure out when to submit your price data. If you submit too late, the Tx might not get included, if submitting too early the price data might not be accurate enough.
  • Claim rewards. Be sure to claim your reward regularly and wrap them so more vote power is gained.

Notes#

  • On the real network PriceSubmitter is deployed at a fixed address 0x1000000000000000000000000000000000000003.

FAQ#

What can I do to generate strong random numbers?#

Use already available random number generators that provide a cryptographically secure (pseudo) random number generator. One good example would be the csprng library for nodejs applications. Keep in mind that you can submit randoms with 256 bits so try to use all the bits for entropy. Strong random numbers can also be generated by using Web3 utils: web3.utils.toBN(web3.utils.randomHex(32))

How do I calculate hash for the commit-reveal scheme?#

The full and up-to-date specification for the commit-reveal scheme is available in specifications on the flare smart contract repo.

The following code snippets demonstrate how hashes can be generated in typescript and python using publicly available web3 libraries.

import BN from "bn.js";
import {
    BigNumber
} from "ethers";
import {
    ethers
} from "hardhat";
const MIN_RANDOM = web3.utils.toBN(2).pow(web3.utils.toBN(128));

function submitHash(ftsoIndices: (number | BN | BigNumber)[],
    prices: (number | BN | BigNumber)[],
    random: number | BN | BigNumber,
    address: string): string {

    return ethers.utils.keccak256(web3.eth.abi.encodeParameters(
        ["uint256[]", "uint256[]", "uint256", "address"],
        [ftsoIndices, prices, random, address]));
}
const ftsoIndices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const randoms = [MIN_RANDOM, MIN_RANDOM.addn(5), MIN_RANDOM.addn(1059),
    MIN_RANDOM.addn(10682), MIN_RANDOM.addn(159726)
];
const prices = [0, 1, 2, 3, 5, 10, 50, 100, 101, 10 ** 5 + 1, 10 ** 8];
const addrs = [accounts[10], accounts[11], accounts[12], accounts[13]];

console.log(`Prices: ${prices}`);
for(let addr of addrs) {
    console.log(`Address: ${addr}`);
    for(let random of randoms) {
        console.log(`\tRandom: ${random}`)
        const hash = submitHash(ftsoIndices, prices, random, addr);
        console.log(`\t\t${hash}`);
    }
}
from typing import List
from web3 import Web3
import eth_abi

minimal_random = 2 ** 128

def submit_price_hash(
    ftsoIndices: List[int], prices: List[int], random: int, address: str
) -> str:
    assert len(ftsoIndices) == len(prices)
    assert list(sorted(ftsoIndices)) == ftsoIndices and len(
        set(ftsoIndices)
    ) == len(ftsoIndices), "Indices are non increasing"
    return Web3.keccak(
        eth_abi.encode_abi(
            ["uint256[]", "uint256[]", "uint256", "address"],
            [ftsoIndices, prices, random, address],
        )
    ).hex()


def test_fun(
    prices: List[int],
    random: int,
    address="0xD7de703D9BBC4602242D0f3149E5fFCD30Eb3ADF",
) -> List[str]:
    return submit_price_hash(list(range(len(prices))), prices, random, address)


addrs = [
    "0xD7de703D9BBC4602242D0f3149E5fFCD30Eb3ADF",
    "0xEa960515F8b4C237730F028cBAcF0a28E7F45dE0",
    "0x3d91185a02774C70287F6c74Dd26d13DFB58ff16",
]
prices = [0, 1, 2, 3, 5, 10, 50, 100, 101, 10 ** 5 + 1, 10 ** 8]
randoms = [
     min_random + r for r in
     [0, 1, 100, 101, 100000000000000000000]
]
for addr in addrs:
    print(f"Address: {addr}")
    for rand in randoms:
        print(f"  Random: {rand}")
        print("    hash:", test_fun(prices, rand, addr))
    print()

Where can I find the contracts I need to interact with as a price provider?#

The PriceSubmitter contract is deployed at a fixed address: 0x1000000000000000000000000000000000000003. All the other contracts are available as read methods on the PriceSubmitter contract. You should periodically check for updates to have up to date information. Any important updates and contract changes will be broadcasted to the community.

Where can I browse the source code and documentation for contracts?#

All the important contracts are verified on the Songbird Explorer. The main smart contract repo is referenced in the Developer Docs section.

What are the important contracts I need to be aware of to be a price provider?#

  1. The most important is the PriceSubmitter where you submit prices. It also has links to the below contracts.
  2. FtsoRegistry: Holds information about specific FTSOs, their symbols, indices and addresses.
  3. FTSOManager: Holds epoch and voting related configuration data and oversees all FTSOs, also gives access to additional useful contracts such as Inflation and Supply contracts.
  4. VoterWhitelister: The contract where a price provider list themselves to submit prices.

How much does it cost to submit prices as price provider?#

Price submissions and reveals are currently discounted and it costs approximately 3-4 SGB per day if all the submission and reveal transactions are successful.

Where can I see for which FTSOs I am eligible to submit prices?#

Each address is whitelisted separately for each FTSO contract. There are two ways to query whitelisting data, one through the VoterWhitelister contract, the other through the PriceSubmitter contract.

How to read whitelisted addresses using the VoterWhitelister contract?#

Per FTSO there is an array of whitelisted addresses. Open the contract and use function #4 getFtsoWhitelistedPriceProviders. Set the required index and check if your address is in this list.

How to read whitelisted addresses using the the PriceSubmitter contract?#

Open the contract and use function #8 voterWhitelistBitmap where you should set the address your would like to query. The function returns a bitmap corresponding to allowed FTSO indices in big-endian format. If you were allowed to submit princess for FTSOs with indices 0, 1 and 3, the returned bitmap would be 11 (in binary 1011)

Which currencies are available on the network?#

The best way to get available currencies is to query the FtsoRegistry that holds information about available FTSOs, their addresses, prices and indices. Songbird currently supports the following symbols: [XRP, LTC, XLM, DOGE, ADA, ALGO, BCH, DGB, BTC, ETH, FIL, SGB], but new ones could be added by governance vote.

Is there a slashing mechanism for non-availability?#

There is currently no slashing for not providing a price. If you do not provide a price in a specific price epoch, your can not gain reward in that epoch. So the unavailability has a direct negative impact on your reward rate as a price provider.

The network time is not the same as local time, is there something wrong?#

Due to the decentralized state of the network, one might experience some occasional time drifts (+-30s). We suggest you keep synchronized local time with global time through Network Time Protocol (NTP) to avoid missing any important submit/reveal periods.

Where can I get information on which prices are rewarded#

Each FTSO emits a PriceFinalized event that contains information about calculated median price and rewarding bounds.

How can I see who has delegated to me#

There is currently no on-chain structure that holds the relevant data. You might want to listen to events emitted by delegations.

The NPM library is written in Typescript, can I use another language to write a price provider?#

You are free to use any language to run the price provider, although some might be more suitable than others. Try using a language that offers good support for Ethereum smart contracts, e.g. web3-your-language. Many successful price providers use different technologies such as: go, C#, python.

Is there any code for writing a price provider in Python?#

This gist showcases the calculation of submit hashes in python using the web3py library.

Are delegations transferable between different addresses?#

Delegations are currently not transferable. Specifically, you can't redelegate the vote power that was delegated to your address.

Does the price epoch vary with each FTSO?#

No, price epoch configurations are governed by FtsoManager (you can get them using the getPriceEpochConfiguration method). This is necessary so that all submissions (and reveals) can happen at the same time.

Can price epoch duration change?#

Price epoch durations are generally fixed and will not change abruptly. Any such change will be broadcasted to the community and be part of a governance decision.

Why am I getting strange reverts on submission?#

One reason could be related to the status of your node. Make sure the node is healthy and has enough peers. See observation-node-faq.md


Last update: 2022-06-29
Back to top