Skip to main content

Change quote feed

This guide will show you how to fetch the latest feed values for two feeds and convert them to a new quote feed. For example, if you need the price of BTC/ETH, you can fetch the latest feed values for BTC/USD and ETH/USD and calculate the price of BTC/ETH = (BTC/USD) / (ETH/USD).

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

import {ContractRegistry} from "@flarenetwork/flare-periphery-contracts/coston2/ContractRegistry.sol";
/* THIS IS A TEST IMPORT, in production use: import {FtsoV2Interface} from "@flarenetwork/flare-periphery-contracts/coston2/FtsoV2Interface.sol"; */
import {TestFtsoV2Interface} from "@flarenetwork/flare-periphery-contracts/coston2/TestFtsoV2Interface.sol";

/**
* THIS IS AN EXAMPLE CONTRACT.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
contract FtsoV2ChangeQuoteFeed {
TestFtsoV2Interface internal ftsoV2;

/**
* Initializing an instance with FtsoV2Interface.
* The contract registry is used to fetch the contract address.
*/
constructor() {
/* THIS IS A TEST METHOD, in production use: ftsoV2 = ContractRegistry.getFtsoV2(); */
ftsoV2 = ContractRegistry.getTestFtsoV2();
}

/**
* @dev Internal function to scale the base feed value to match the decimals of the quote feed.
*/
function _scaleBaseFeedValue(
uint256 _baseFeedValue,
uint8 _baseFeedDecimals,
uint8 _quoteDecimals
) internal pure returns (uint256) {
if (_baseFeedDecimals < _quoteDecimals) {
// Scale up if base feed decimals are less than quote feed decimals
return
_baseFeedValue *
10 ** uint256(_quoteDecimals - _baseFeedDecimals);
} else if (_baseFeedDecimals > _quoteDecimals) {
// Scale down if base feed decimals are more than quote feed decimals
return
_baseFeedValue /
10 ** uint256(_baseFeedDecimals - _quoteDecimals);
} else {
// No scaling needed if decimals are equal
return _baseFeedValue;
}
}

/**
* @dev Function to compute the new quote feed value based on the base and quote feed values.
* @param _baseAndQuoteFeedIds Array containing the IDs of the base and quote feeds.
* @return The computed new quote feed value.
*/
function getNewQuoteFeedValue(
bytes21[] calldata _baseAndQuoteFeedIds
) external view returns (uint256) {
require(
_baseAndQuoteFeedIds.length == 2,
"Invalid feed indexes. Please provide exactly two indexes."
);
// Fetch current feeds
(uint256[] memory feedValues, int8[] memory decimals, ) = ftsoV2
.getFeedsById(_baseAndQuoteFeedIds);
uint8 newQuoteDecimals = uint8(decimals[1]);
// Scale the base feed value to match the quote feed decimals
uint256 scaledBaseFeedValue = _scaleBaseFeedValue(
feedValues[0],
uint8(decimals[0]),
newQuoteDecimals
);
// Prevent division by zero
require(feedValues[1] != 0, "Division by zero");
// Compute the new quote feed value
uint256 newQuoteFeedValue = (scaledBaseFeedValue *
10 ** uint256(newQuoteDecimals)) / feedValues[1];
return newQuoteFeedValue;
}
}

Don't use test interfaces in production

The TestFtsoV2Interface is for testing only, with all methods as view to allow rapid development without gas costs or state changes. For production, use FtsoV2Interface, which includes payable methods required for real transactions and state modifications. Make the following changes to FtsoV2ChangeQuoteFeed.sol:

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

contract FtsoV2ChangeQuoteFeed {
constructor() {
- ftsoV2 = ContractRegistry.getTestFtsoV2();
+ ftsoV2 = ContractRegistry.getFtsoV2();
}
}
Set EVM Version to London
  • Using Remix: Set EVM version to london in the Advanced Configurations section of the Solidity Compiler tab:

  • Using Hardhat or Foundry: Set EVM version to london in hardhat.config.ts or foundry.toml.

  • Using Standard Solidity JSON: Set evmVersion to london:

    {
    "settings": {
    "optimizer": {
    /* ... */
    },
    "evmVersion": "london"
    }
    }
  • Using solc CLI: Set --evm-version to london:

    solc --evm-version london <args>
Didn't understand the Solidity code?
  • Purpose: This contract interacts with the Flare Network to fetch feed values and compute a new quote feed value based on the base and quote feed values.

  • Dependencies:

    • ContractRegistry.sol: Used to get the addresses of various contracts on the Flare network.
    • TestFtsoV2Interface.sol: This interface allows interaction with the FTSOv2 contract, which provides real-time price feeds for various assets.
  • State Variables:

    • ftsoV2: This is a state variable of type TestFtsoV2Interface. It will hold the address of the FTSO V2 contract once initialized.
  • Constructor:

    • The constructor is a special function that runs only once when the contract is deployed. It initializes the ftsoV2 state variable by fetching the FTSO V2 contract address using the ContractRegistry.
  • Internal Function _scaleBaseFeedValue:

    • Scales the base feed value to match the decimals of the quote feed.
    • Adjusts the feed value by scaling up or down depending on the difference in decimals.
  • External Function getNewQuoteFeedValue:

    • Accepts an array of base and quote feed IDs.
    • Fetches current feed values and decimals using ftsoV2.
    • Scales the base feed value to match the quote feed decimals.
    • Computes and returns the new quote feed value by adjusting for the decimal differences and performing a calculation.
  • Key Validations:

    • Ensures exactly two feed indexes are provided.
    • Prevents division by zero during the computation of the new quote feed value.