Make a volatility incentive
Before reading this guide, make sure you understand FTSOv2's Volatility Incentive Mechanism.
This guide provides code examples demonstrating how to make an FTSOv2 volatility incentive offer using various programming languages. To make a volatility incentive offer, you need three key pieces of information:
-
RPC Endpoint URL: The RPC Endpoint URL determines which network your code will interact with. You can use a node provider service or point to your own RPC node. A comprehensive list of public and private RPC endpoints for all Flare networks is available on the Network Configuration page.
-
Contract Address: The address for the
FastUpdateIncentiveManager
contract varies by network. You can obtain this address in two ways:- From the Solidity Reference page: Find the
FastUpdateIncentiveManager
address for each network on the Solidity Reference page.
OR
- Query the FlareContractRegistry Contract: The
FlareContractRegistry
contract has the same address across all networks. You can query it to get theFastUpdateIncentiveManager
contract address. Refer to the specific language guides for examples:
- From the Solidity Reference page: Find the
-
Cost of Increasing the Sample Size: FTSOv2 allows you to increase the sample size, i.e., the expected number of providers who can submit a block-latency feed update. The cost for this increases dynamically with the expected sample size. A single volatility incentive lasts for a period of 8 blocks.
All examples in this guide are available at developer-hub/examples.
- web3.js
- ethers.js
- web3.py
- alloy-rs
- go-ethereum
This example uses web3.js to make an FTSOv2 volatility incentive offer on Flare Testnet Coston2.
// THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.
import { Web3 } from "web3";
// FastUpdatesIncentiveManager address (Flare Testnet Coston2)
// See https://dev.flare.network/ftso/solidity-reference
const INCENTIVE_ADDRESS = "0x58fb598EC6DB6901aA6F26a9A2087E9274128E59";
const RPC_URL = "https://coston2-api.flare.network/ext/C/rpc";
// ABI for FastUpdatesIncentiveManager contract
const ABI =
'[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_governanceSettings","internalType":"contract IGovernanceSettings"},{"type":"address","name":"_initialGovernance","internalType":"address"},{"type":"address","name":"_addressUpdater","internalType":"address"},{"type":"uint256","name":"_ss","internalType":"SampleSize"},{"type":"uint256","name":"_r","internalType":"Range"},{"type":"uint256","name":"_sil","internalType":"SampleSize"},{"type":"uint256","name":"_ril","internalType":"Range"},{"type":"uint256","name":"_x","internalType":"Fee"},{"type":"uint256","name":"_rip","internalType":"Fee"},{"type":"uint256","name":"_dur","internalType":"uint256"}]},{"type":"event","name":"DailyAuthorizedInflationSet","inputs":[{"type":"uint256","name":"authorizedAmountWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceCallTimelocked","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256","indexed":false},{"type":"bytes","name":"encodedCall","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceInitialised","inputs":[{"type":"address","name":"initialGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernedProductionModeEntered","inputs":[{"type":"address","name":"governanceSettings","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"IncentiveOffered","inputs":[{"type":"uint24","name":"rewardEpochId","internalType":"uint24","indexed":true},{"type":"uint256","name":"rangeIncrease","internalType":"Range","indexed":false},{"type":"uint256","name":"sampleSizeIncrease","internalType":"SampleSize","indexed":false},{"type":"uint256","name":"offerAmount","internalType":"Fee","indexed":false}],"anonymous":false},{"type":"event","name":"InflationReceived","inputs":[{"type":"uint256","name":"amountReceivedWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"InflationRewardsOffered","inputs":[{"type":"uint24","name":"rewardEpochId","internalType":"uint24","indexed":true},{"type":"tuple[]","name":"feedConfigurations","internalType":"struct IFastUpdatesConfiguration.FeedConfiguration[]","indexed":false,"components":[{"type":"bytes21","name":"feedId","internalType":"bytes21"},{"type":"uint32","name":"rewardBandValue","internalType":"uint32"},{"type":"uint24","name":"inflationShare","internalType":"uint24"}]},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallCanceled","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallExecuted","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"advance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dailyAuthorizedInflation","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fastUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFastUpdatesConfiguration"}],"name":"fastUpdatesConfiguration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IIFlareSystemsManager"}],"name":"flareSystemsManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"_addressUpdater","internalType":"address"}],"name":"getAddressUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Scale"}],"name":"getBaseScale","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getContractName","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Fee"}],"name":"getCurrentSampleSizeIncreasePrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExpectedBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"SampleSize"}],"name":"getExpectedSampleSize","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getIncentiveDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getInflationAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Precision"}],"name":"getPrecision","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Range"}],"name":"getRange","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Scale"}],"name":"getScale","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_lockedFundsWei","internalType":"uint256"},{"type":"uint256","name":"_totalInflationAuthorizedWei","internalType":"uint256"},{"type":"uint256","name":"_totalClaimedWei","internalType":"uint256"}],"name":"getTokenPoolSupplyData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IGovernanceSettings"}],"name":"governanceSettings","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_governanceSettings","internalType":"contract IGovernanceSettings"},{"type":"address","name":"_initialGovernance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExecutor","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastInflationAuthorizationReceivedTs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastInflationReceivedTs","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"offerIncentive","inputs":[{"type":"tuple","name":"_offer","internalType":"struct IFastUpdateIncentiveManager.IncentiveOffer","components":[{"type":"uint256","name":"rangeIncrease","internalType":"Range"},{"type":"uint256","name":"rangeLimit","internalType":"Range"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"productionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Range"}],"name":"rangeIncreaseLimit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Fee"}],"name":"rangeIncreasePrice","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"receiveInflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IIRewardManager"}],"name":"rewardManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"SampleSize"}],"name":"sampleIncreaseLimit","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDailyAuthorizedInflation","inputs":[{"type":"uint256","name":"_toAuthorizeWei","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setIncentiveParameters","inputs":[{"type":"uint256","name":"_ss","internalType":"SampleSize"},{"type":"uint256","name":"_r","internalType":"Range"},{"type":"uint256","name":"_x","internalType":"Fee"},{"type":"uint256","name":"_dur","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRangeIncreaseLimit","inputs":[{"type":"uint256","name":"_lim","internalType":"Range"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRangeIncreasePrice","inputs":[{"type":"uint256","name":"_price","internalType":"Fee"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSampleIncreaseLimit","inputs":[{"type":"uint256","name":"_lim","internalType":"SampleSize"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"switchToProductionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256"},{"type":"bytes","name":"encodedCall","internalType":"bytes"}],"name":"timelockedCalls","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationAuthorizedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationReceivedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationRewardsOfferedWei","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"triggerRewardEpochSwitchover","inputs":[{"type":"uint24","name":"_currentRewardEpochId","internalType":"uint24"},{"type":"uint64","name":"_currentRewardEpochExpectedEndTs","internalType":"uint64"},{"type":"uint64","name":"_rewardEpochDurationSeconds","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateContractAddresses","inputs":[{"type":"bytes32[]","name":"_contractNameHashes","internalType":"bytes32[]"},{"type":"address[]","name":"_contractAddresses","internalType":"address[]"}]}]';
async function main() {
// Connect to an RPC node
const w3 = new Web3(RPC_URL);
const privateKey = process.env.ACCOUNT_PRIVATE_KEY.toString();
const wallet = w3.eth.accounts.wallet.add(privateKey);
// Set up contract instance
const incentive = new w3.eth.Contract(JSON.parse(ABI), INCENTIVE_ADDRESS);
// Get the current sample size, sample size increase price, precision, and scale
const sampleSizeIncreasePrice = await incentive.methods
.getCurrentSampleSizeIncreasePrice()
.call();
console.log(
"Sample Size Increase Price: %i, Current Sample Size: %i, Current Precision %i, Current Scale %i",
sampleSizeIncreasePrice,
await incentive.methods.getExpectedSampleSize().call(),
await incentive.methods.getPrecision().call(),
await incentive.methods.getScale().call(),
);
// Offer the incentive
const tx = await incentive.methods
.offerIncentive({ rangeIncrease: 0, rangeLimit: 0 })
.send({
from: wallet[0].address,
nonce: await w3.eth.getTransactionCount(wallet[0].address),
gasPrice: await w3.eth.getGasPrice(),
value: sampleSizeIncreasePrice,
});
console.log("Transaction hash:", tx.transactionHash);
// Log the new sample size, precision, and scale
console.log(
"New Sample Size: %i, New Precision %i, New Scale %i",
await incentive.methods.getExpectedSampleSize().call(),
await incentive.methods.getPrecision().call(),
await incentive.methods.getScale().call(),
);
}
main();
This example uses ethers.js to make an FTSOv2 volatility incentive offer on Flare Testnet Coston2.
// THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.
import { ethers } from "ethers";
// FastUpdatesIncentiveManager address (Flare Testnet Coston2)
// See https://dev.flare.network/ftso/solidity-reference
const INCENTIVE_ADDRESS = "0x003e9bD18f73e0B25BED0DC8382Bde6aa999525c";
const RPC_URL = "https://coston2-api.flare.network/ext/C/rpc";
// ABI for FastUpdatesIncentiveManager contract
const ABI =
'[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_governanceSettings","internalType":"contract IGovernanceSettings"},{"type":"address","name":"_initialGovernance","internalType":"address"},{"type":"address","name":"_addressUpdater","internalType":"address"},{"type":"uint256","name":"_ss","internalType":"SampleSize"},{"type":"uint256","name":"_r","internalType":"Range"},{"type":"uint256","name":"_sil","internalType":"SampleSize"},{"type":"uint256","name":"_ril","internalType":"Range"},{"type":"uint256","name":"_x","internalType":"Fee"},{"type":"uint256","name":"_rip","internalType":"Fee"},{"type":"uint256","name":"_dur","internalType":"uint256"}]},{"type":"event","name":"DailyAuthorizedInflationSet","inputs":[{"type":"uint256","name":"authorizedAmountWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceCallTimelocked","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256","indexed":false},{"type":"bytes","name":"encodedCall","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceInitialised","inputs":[{"type":"address","name":"initialGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernedProductionModeEntered","inputs":[{"type":"address","name":"governanceSettings","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"IncentiveOffered","inputs":[{"type":"uint24","name":"rewardEpochId","internalType":"uint24","indexed":true},{"type":"uint256","name":"rangeIncrease","internalType":"Range","indexed":false},{"type":"uint256","name":"sampleSizeIncrease","internalType":"SampleSize","indexed":false},{"type":"uint256","name":"offerAmount","internalType":"Fee","indexed":false}],"anonymous":false},{"type":"event","name":"InflationReceived","inputs":[{"type":"uint256","name":"amountReceivedWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"InflationRewardsOffered","inputs":[{"type":"uint24","name":"rewardEpochId","internalType":"uint24","indexed":true},{"type":"tuple[]","name":"feedConfigurations","internalType":"struct IFastUpdatesConfiguration.FeedConfiguration[]","indexed":false,"components":[{"type":"bytes21","name":"feedId","internalType":"bytes21"},{"type":"uint32","name":"rewardBandValue","internalType":"uint32"},{"type":"uint24","name":"inflationShare","internalType":"uint24"}]},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallCanceled","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallExecuted","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"advance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dailyAuthorizedInflation","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fastUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFastUpdatesConfiguration"}],"name":"fastUpdatesConfiguration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IIFlareSystemsManager"}],"name":"flareSystemsManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"_addressUpdater","internalType":"address"}],"name":"getAddressUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Scale"}],"name":"getBaseScale","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getContractName","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Fee"}],"name":"getCurrentSampleSizeIncreasePrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExpectedBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"SampleSize"}],"name":"getExpectedSampleSize","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getIncentiveDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getInflationAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Precision"}],"name":"getPrecision","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Range"}],"name":"getRange","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Scale"}],"name":"getScale","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_lockedFundsWei","internalType":"uint256"},{"type":"uint256","name":"_totalInflationAuthorizedWei","internalType":"uint256"},{"type":"uint256","name":"_totalClaimedWei","internalType":"uint256"}],"name":"getTokenPoolSupplyData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IGovernanceSettings"}],"name":"governanceSettings","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_governanceSettings","internalType":"contract IGovernanceSettings"},{"type":"address","name":"_initialGovernance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExecutor","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastInflationAuthorizationReceivedTs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastInflationReceivedTs","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"offerIncentive","inputs":[{"type":"tuple","name":"_offer","internalType":"struct IFastUpdateIncentiveManager.IncentiveOffer","components":[{"type":"uint256","name":"rangeIncrease","internalType":"Range"},{"type":"uint256","name":"rangeLimit","internalType":"Range"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"productionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Range"}],"name":"rangeIncreaseLimit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Fee"}],"name":"rangeIncreasePrice","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"receiveInflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IIRewardManager"}],"name":"rewardManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"SampleSize"}],"name":"sampleIncreaseLimit","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDailyAuthorizedInflation","inputs":[{"type":"uint256","name":"_toAuthorizeWei","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setIncentiveParameters","inputs":[{"type":"uint256","name":"_ss","internalType":"SampleSize"},{"type":"uint256","name":"_r","internalType":"Range"},{"type":"uint256","name":"_x","internalType":"Fee"},{"type":"uint256","name":"_dur","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRangeIncreaseLimit","inputs":[{"type":"uint256","name":"_lim","internalType":"Range"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRangeIncreasePrice","inputs":[{"type":"uint256","name":"_price","internalType":"Fee"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSampleIncreaseLimit","inputs":[{"type":"uint256","name":"_lim","internalType":"SampleSize"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"switchToProductionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256"},{"type":"bytes","name":"encodedCall","internalType":"bytes"}],"name":"timelockedCalls","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationAuthorizedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationReceivedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationRewardsOfferedWei","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"triggerRewardEpochSwitchover","inputs":[{"type":"uint24","name":"_currentRewardEpochId","internalType":"uint24"},{"type":"uint64","name":"_currentRewardEpochExpectedEndTs","internalType":"uint64"},{"type":"uint64","name":"_rewardEpochDurationSeconds","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateContractAddresses","inputs":[{"type":"bytes32[]","name":"_contractNameHashes","internalType":"bytes32[]"},{"type":"address[]","name":"_contractAddresses","internalType":"address[]"}]}]';
async function main() {
// Connect to an RPC node
const provider = new ethers.JsonRpcProvider(RPC_URL);
const privateKey = process.env.ACCOUNT_PRIVATE_KEY.toString();
const signer = new ethers.Wallet(privateKey, provider);
// Set up contract instance
const incentive = new ethers.Contract(
INCENTIVE_ADDRESS,
JSON.parse(ABI),
signer,
);
// Get the sample size increase price, sample size, precision, and scale
const sampleSizeIncreasePrice =
await incentive.getCurrentSampleSizeIncreasePrice();
console.log(
"Sample Size Increase Price: %i, Current Sample Size: %i, Current Precision %i, Current Scale %i",
sampleSizeIncreasePrice,
await incentive.getExpectedSampleSize(),
await incentive.getPrecision(),
await incentive.getScale(),
);
// Offer the incentive
const tx = await incentive.offerIncentive(
{ rangeIncrease: 0, rangeLimit: 0 },
{
nonce: await provider.getTransactionCount(signer.address),
value: sampleSizeIncreasePrice,
},
);
console.log("Transaction hash:", tx.hash);
await tx.wait();
// Log the new sample size, precision, and scale
console.log(
"Current Sample Size: %i, Current Precision %i, Current Scale %i",
await incentive.getExpectedSampleSize(),
await incentive.getPrecision(),
await incentive.getScale(),
);
}
main();
This example uses web3.py to make an FTSOv2 volatility incentive offer on Flare Testnet Coston2.
# THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.
import asyncio
import os
from web3 import AsyncHTTPProvider, AsyncWeb3
# FastUpdatesIncentiveManager address (Flare Testnet Coston2)
# See https://dev.flare.network/ftso/solidity-reference
INCENTIVE_ADDRESS = "0x003e9bD18f73e0B25BED0DC8382Bde6aa999525c"
RPC_URL = "https://coston2-api.flare.network/ext/C/rpc"
# ABI for FastUpdatesIncentiveManager contract
ABI = '[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_governanceSettings","internalType":"contract IGovernanceSettings"},{"type":"address","name":"_initialGovernance","internalType":"address"},{"type":"address","name":"_addressUpdater","internalType":"address"},{"type":"uint256","name":"_ss","internalType":"SampleSize"},{"type":"uint256","name":"_r","internalType":"Range"},{"type":"uint256","name":"_sil","internalType":"SampleSize"},{"type":"uint256","name":"_ril","internalType":"Range"},{"type":"uint256","name":"_x","internalType":"Fee"},{"type":"uint256","name":"_rip","internalType":"Fee"},{"type":"uint256","name":"_dur","internalType":"uint256"}]},{"type":"event","name":"DailyAuthorizedInflationSet","inputs":[{"type":"uint256","name":"authorizedAmountWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceCallTimelocked","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256","indexed":false},{"type":"bytes","name":"encodedCall","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceInitialised","inputs":[{"type":"address","name":"initialGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernedProductionModeEntered","inputs":[{"type":"address","name":"governanceSettings","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"IncentiveOffered","inputs":[{"type":"uint24","name":"rewardEpochId","internalType":"uint24","indexed":true},{"type":"uint256","name":"rangeIncrease","internalType":"Range","indexed":false},{"type":"uint256","name":"sampleSizeIncrease","internalType":"SampleSize","indexed":false},{"type":"uint256","name":"offerAmount","internalType":"Fee","indexed":false}],"anonymous":false},{"type":"event","name":"InflationReceived","inputs":[{"type":"uint256","name":"amountReceivedWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"InflationRewardsOffered","inputs":[{"type":"uint24","name":"rewardEpochId","internalType":"uint24","indexed":true},{"type":"tuple[]","name":"feedConfigurations","internalType":"struct IFastUpdatesConfiguration.FeedConfiguration[]","indexed":false,"components":[{"type":"bytes21","name":"feedId","internalType":"bytes21"},{"type":"uint32","name":"rewardBandValue","internalType":"uint32"},{"type":"uint24","name":"inflationShare","internalType":"uint24"}]},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallCanceled","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallExecuted","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"advance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dailyAuthorizedInflation","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fastUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFastUpdatesConfiguration"}],"name":"fastUpdatesConfiguration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IIFlareSystemsManager"}],"name":"flareSystemsManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"_addressUpdater","internalType":"address"}],"name":"getAddressUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Scale"}],"name":"getBaseScale","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getContractName","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Fee"}],"name":"getCurrentSampleSizeIncreasePrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExpectedBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"SampleSize"}],"name":"getExpectedSampleSize","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getIncentiveDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getInflationAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Precision"}],"name":"getPrecision","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Range"}],"name":"getRange","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Scale"}],"name":"getScale","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_lockedFundsWei","internalType":"uint256"},{"type":"uint256","name":"_totalInflationAuthorizedWei","internalType":"uint256"},{"type":"uint256","name":"_totalClaimedWei","internalType":"uint256"}],"name":"getTokenPoolSupplyData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IGovernanceSettings"}],"name":"governanceSettings","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_governanceSettings","internalType":"contract IGovernanceSettings"},{"type":"address","name":"_initialGovernance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExecutor","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastInflationAuthorizationReceivedTs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastInflationReceivedTs","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"offerIncentive","inputs":[{"type":"tuple","name":"_offer","internalType":"struct IFastUpdateIncentiveManager.IncentiveOffer","components":[{"type":"uint256","name":"rangeIncrease","internalType":"Range"},{"type":"uint256","name":"rangeLimit","internalType":"Range"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"productionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Range"}],"name":"rangeIncreaseLimit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Fee"}],"name":"rangeIncreasePrice","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"receiveInflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IIRewardManager"}],"name":"rewardManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"SampleSize"}],"name":"sampleIncreaseLimit","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDailyAuthorizedInflation","inputs":[{"type":"uint256","name":"_toAuthorizeWei","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setIncentiveParameters","inputs":[{"type":"uint256","name":"_ss","internalType":"SampleSize"},{"type":"uint256","name":"_r","internalType":"Range"},{"type":"uint256","name":"_x","internalType":"Fee"},{"type":"uint256","name":"_dur","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRangeIncreaseLimit","inputs":[{"type":"uint256","name":"_lim","internalType":"Range"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRangeIncreasePrice","inputs":[{"type":"uint256","name":"_price","internalType":"Fee"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSampleIncreaseLimit","inputs":[{"type":"uint256","name":"_lim","internalType":"SampleSize"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"switchToProductionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256"},{"type":"bytes","name":"encodedCall","internalType":"bytes"}],"name":"timelockedCalls","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationAuthorizedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationReceivedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationRewardsOfferedWei","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"triggerRewardEpochSwitchover","inputs":[{"type":"uint24","name":"_currentRewardEpochId","internalType":"uint24"},{"type":"uint64","name":"_currentRewardEpochExpectedEndTs","internalType":"uint64"},{"type":"uint64","name":"_rewardEpochDurationSeconds","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateContractAddresses","inputs":[{"type":"bytes32[]","name":"_contractNameHashes","internalType":"bytes32[]"},{"type":"address[]","name":"_contractAddresses","internalType":"address[]"}]}]' # noqa: E501
async def main() -> None:
# Connect to an RPC node
w3 = AsyncWeb3(
AsyncHTTPProvider(RPC_URL),
)
private_key = os.getenv("ACCOUNT_PRIVATE_KEY")
account = w3.eth.account.from_key(private_key)
# Set up contract instance
incentive = w3.eth.contract(
address=w3.to_checksum_address(INCENTIVE_ADDRESS), abi=ABI
)
# Get the current sample size, sample size increase price, precision, and scale
sample_size_increase_price = (
await incentive.functions.getCurrentSampleSizeIncreasePrice().call()
)
print(
f"Sample Size Increase Price: {sample_size_increase_price},"
f"Sample Size: {await incentive.functions.getExpectedSampleSize().call()},"
f"Range: {await incentive.functions.getRange().call()},"
f"Scale: {await incentive.functions.getScale().call()},"
)
# Offer the incentive
tx = await incentive.functions.offerIncentive(
{"rangeIncrease": 0, "rangeLimit": 0}
).build_transaction(
{
"from": account.address,
"nonce": await w3.eth.get_transaction_count(account.address),
"gasPrice": await w3.eth.gas_price,
"value": sample_size_increase_price,
}
)
signed_tx = w3.eth.account.sign_transaction(tx, private_key=private_key)
tx_hash = await w3.eth.send_raw_transaction(signed_tx.raw_transaction)
print("Transaction hash:", tx_hash.hex())
await w3.eth.wait_for_transaction_receipt(tx_hash)
# Print the new sample size, precision, and scale
print(
f"Sample Size Increase Price: {sample_size_increase_price},"
f"New Sample Size: {await incentive.functions.getExpectedSampleSize().call()},"
f"New Range: {await incentive.functions.getRange().call()},"
f"New Scale: {await incentive.functions.getScale().call()},"
)
if __name__ == "__main__":
asyncio.run(main())
This example uses alloy-rs to make an FTSOv2 volatility incentive offer on Flare Testnet Coston2.
cargo add alloy eyre tokio --features alloy/full,tokio/rt,tokio/rt-multi-thread,tokio/macros
// THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.
use alloy::{
network::EthereumWallet, primitives::U256, providers::ProviderBuilder,
signers::local::PrivateKeySigner, sol,
};
use eyre::Result;
sol!(
#[sol(rpc)]
FastUpdatesIncentiveManager,
r#"[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_governanceSettings","internalType":"contract IGovernanceSettings"},{"type":"address","name":"_initialGovernance","internalType":"address"},{"type":"address","name":"_addressUpdater","internalType":"address"},{"type":"uint256","name":"_ss","internalType":"SampleSize"},{"type":"uint256","name":"_r","internalType":"Range"},{"type":"uint256","name":"_sil","internalType":"SampleSize"},{"type":"uint256","name":"_ril","internalType":"Range"},{"type":"uint256","name":"_x","internalType":"Fee"},{"type":"uint256","name":"_rip","internalType":"Fee"},{"type":"uint256","name":"_dur","internalType":"uint256"}]},{"type":"event","name":"DailyAuthorizedInflationSet","inputs":[{"type":"uint256","name":"authorizedAmountWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceCallTimelocked","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256","indexed":false},{"type":"bytes","name":"encodedCall","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceInitialised","inputs":[{"type":"address","name":"initialGovernance","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"GovernedProductionModeEntered","inputs":[{"type":"address","name":"governanceSettings","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"IncentiveOffered","inputs":[{"type":"uint24","name":"rewardEpochId","internalType":"uint24","indexed":true},{"type":"uint256","name":"rangeIncrease","internalType":"Range","indexed":false},{"type":"uint256","name":"sampleSizeIncrease","internalType":"SampleSize","indexed":false},{"type":"uint256","name":"offerAmount","internalType":"Fee","indexed":false}],"anonymous":false},{"type":"event","name":"InflationReceived","inputs":[{"type":"uint256","name":"amountReceivedWei","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"InflationRewardsOffered","inputs":[{"type":"uint24","name":"rewardEpochId","internalType":"uint24","indexed":true},{"type":"tuple[]","name":"feedConfigurations","internalType":"struct IFastUpdatesConfiguration.FeedConfiguration[]","indexed":false,"components":[{"type":"bytes21","name":"feedId","internalType":"bytes21"},{"type":"uint32","name":"rewardBandValue","internalType":"uint32"},{"type":"uint24","name":"inflationShare","internalType":"uint24"}]},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallCanceled","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TimelockedGovernanceCallExecuted","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"advance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancelGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dailyAuthorizedInflation","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceCall","inputs":[{"type":"bytes4","name":"_selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"fastUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFastUpdatesConfiguration"}],"name":"fastUpdatesConfiguration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IIFlareSystemsManager"}],"name":"flareSystemsManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"_addressUpdater","internalType":"address"}],"name":"getAddressUpdater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Scale"}],"name":"getBaseScale","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getContractName","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Fee"}],"name":"getCurrentSampleSizeIncreasePrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getExpectedBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"SampleSize"}],"name":"getExpectedSampleSize","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getIncentiveDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getInflationAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Precision"}],"name":"getPrecision","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Range"}],"name":"getRange","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Scale"}],"name":"getScale","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_lockedFundsWei","internalType":"uint256"},{"type":"uint256","name":"_totalInflationAuthorizedWei","internalType":"uint256"},{"type":"uint256","name":"_totalClaimedWei","internalType":"uint256"}],"name":"getTokenPoolSupplyData","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"governance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IGovernanceSettings"}],"name":"governanceSettings","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialise","inputs":[{"type":"address","name":"_governanceSettings","internalType":"contract IGovernanceSettings"},{"type":"address","name":"_initialGovernance","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExecutor","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastInflationAuthorizationReceivedTs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastInflationReceivedTs","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"offerIncentive","inputs":[{"type":"tuple","name":"_offer","internalType":"struct IFastUpdateIncentiveManager.IncentiveOffer","components":[{"type":"uint256","name":"rangeIncrease","internalType":"Range"},{"type":"uint256","name":"rangeLimit","internalType":"Range"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"productionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Range"}],"name":"rangeIncreaseLimit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"Fee"}],"name":"rangeIncreasePrice","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"receiveInflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IIRewardManager"}],"name":"rewardManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"SampleSize"}],"name":"sampleIncreaseLimit","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDailyAuthorizedInflation","inputs":[{"type":"uint256","name":"_toAuthorizeWei","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setIncentiveParameters","inputs":[{"type":"uint256","name":"_ss","internalType":"SampleSize"},{"type":"uint256","name":"_r","internalType":"Range"},{"type":"uint256","name":"_x","internalType":"Fee"},{"type":"uint256","name":"_dur","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRangeIncreaseLimit","inputs":[{"type":"uint256","name":"_lim","internalType":"Range"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRangeIncreasePrice","inputs":[{"type":"uint256","name":"_price","internalType":"Fee"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSampleIncreaseLimit","inputs":[{"type":"uint256","name":"_lim","internalType":"SampleSize"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"switchToProductionMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"allowedAfterTimestamp","internalType":"uint256"},{"type":"bytes","name":"encodedCall","internalType":"bytes"}],"name":"timelockedCalls","inputs":[{"type":"bytes4","name":"selector","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationAuthorizedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationReceivedWei","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalInflationRewardsOfferedWei","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"triggerRewardEpochSwitchover","inputs":[{"type":"uint24","name":"_currentRewardEpochId","internalType":"uint24"},{"type":"uint64","name":"_currentRewardEpochExpectedEndTs","internalType":"uint64"},{"type":"uint64","name":"_rewardEpochDurationSeconds","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateContractAddresses","inputs":[{"type":"bytes32[]","name":"_contractNameHashes","internalType":"bytes32[]"},{"type":"address[]","name":"_contractAddresses","internalType":"address[]"}]}]"#
);
#[tokio::main]
async fn main() -> Result<()> {
// Get private key from environment
let private_key = std::env::var("ACCOUNT_PRIVATE_KEY")?;
// FastUpdatesIncentiveManager address (Flare Testnet Coston2)
// See https://dev.flare.network/ftso/solidity-reference
let incentive_address = "0x003e9bD18f73e0B25BED0DC8382Bde6aa999525c".parse()?;
// Set up wallet and provider
let signer: PrivateKeySigner = private_key.parse().unwrap();
let wallet = EthereumWallet::from(signer.clone());
let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(wallet)
.on_http("https://coston2-api.flare.network/ext/C/rpc".parse()?);
// Set up contract instance
let incentive = FastUpdatesIncentiveManager::new(incentive_address, provider);
// Get the current sample size, sample size increase price, range, and scale
let FastUpdatesIncentiveManager::getCurrentSampleSizeIncreasePriceReturn {
_0: sample_size_increase_price,
} = incentive.getCurrentSampleSizeIncreasePrice().call().await?;
let FastUpdatesIncentiveManager::getExpectedSampleSizeReturn {
_0: expected_sample_size,
} = incentive.getExpectedSampleSize().call().await?;
let FastUpdatesIncentiveManager::getRangeReturn { _0: range } =
incentive.getRange().call().await?;
let FastUpdatesIncentiveManager::getScaleReturn { _0: scale } =
incentive.getScale().call().await?;
println!(
"Sample Size Increase Price: {:?} ",
sample_size_increase_price
);
println!("Current Sample Size: {:?} ", expected_sample_size);
println!("Current Range: {:?} ", range);
println!("Current Scale: {:?} ", scale);
// Offer the incentive
let offer = FastUpdatesIncentiveManager::IncentiveOffer {
rangeIncrease: U256::from(0),
rangeLimit: U256::from(0),
};
let tx_hash = incentive
.offerIncentive(offer)
.value(sample_size_increase_price)
.send()
.await?
.watch()
.await?;
println!("Offer Incentive Tx Hash: {:?}", tx_hash);
// Get the new sample size increase price, sample size, range, and scale
let FastUpdatesIncentiveManager::getCurrentSampleSizeIncreasePriceReturn {
_0: sample_size_increase_price,
} = incentive.getCurrentSampleSizeIncreasePrice().call().await?;
let FastUpdatesIncentiveManager::getExpectedSampleSizeReturn {
_0: exp_sample_size,
} = incentive.getExpectedSampleSize().call().await?;
let FastUpdatesIncentiveManager::getRangeReturn { _0: range } =
incentive.getRange().call().await?;
let FastUpdatesIncentiveManager::getScaleReturn { _0: scale } =
incentive.getScale().call().await?;
println!(
"Sample Size Increase Price: {:?} ",
sample_size_increase_price
);
println!("Current Sample Size: {:?} ", exp_sample_size);
println!("Current Range: {:?} ", range);
println!("Current Scale: {:?} ", scale);
Ok(())
}
This example uses the Go API from Geth to make an FTSOv2 volatility incentive offer on Flare Testnet Coston2.
go get github.com/ethereum/go-ethereum/ethclient
go get github.com/ethereum/go-ethereum/accounts
The project structure should look like:
developer-hub-go/
├── coston2/
│ └── *.go
├── flare/
│ └── *.go
├── main.go
├── go.mod
└── go.sum
With Go, you need to manually fetch the contract's ABI and generate the Go bindings. Copy the FastUpdatesIncentiveManager ABI and paste it into a file named FastUpdatesIncentiveManager.abi
, located in the root of your project, i.e. same level as go.mod
. Then using abigen, generate the Go bindings.
abigen --abi FastUpdatesIncentiveManager.abi --pkg coston2 --type FastUpdatesIncentiveManager --out coston2/FastUpdatesIncentiveManager.go
// THIS IS EXAMPLE CODE. DO NOT USE THIS CODE IN PRODUCTION.
package coston2
import (
"context"
"fmt"
"math/big"
"os"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
)
func MakeVolatilityIncentive() {
// Get private key from environment
privateKey, _ := crypto.HexToECDSA(os.Getenv("ACCOUNT_PRIVATE_KEY")[2:])
// FastUpdatesIncentiveManager address (Flare Testnet Coston2)
// See https://dev.flare.network/ftso/solidity-reference
incentiveAddress := common.HexToAddress("0x003e9bD18f73e0B25BED0DC8382Bde6aa999525c")
// Connect to an RPC node
client, _ := ethclient.Dial("https://coston2-api.flare.network/ext/C/rpc")
// Set up contract instance
incentive, _ := NewFastUpdatesIncentiveManager(incentiveAddress, client)
// Get the current sample size, sample size increase price, precision, and scale
opts := &bind.CallOpts{Context: context.Background()}
sampleSizeIncreasePrice, _ := incentive.GetCurrentSampleSizeIncreasePrice(opts)
expectedSampleSize, _ := incentive.GetExpectedSampleSize(opts)
rangeVal, _ := incentive.GetRange(opts)
scale, _ := incentive.GetScale(opts)
fmt.Println("Sample Size Increase Price:", sampleSizeIncreasePrice)
fmt.Println("Current Sample Size:", expectedSampleSize)
fmt.Println("Current Range:", rangeVal)
fmt.Println("Current Scale:", scale)
// Offer the incentive
offer := IFastUpdateIncentiveManagerIncentiveOffer{
RangeIncrease: big.NewInt(0),
RangeLimit: big.NewInt(0),
}
transactor, _ := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(114))
transactor.Value = sampleSizeIncreasePrice
tx, _ := incentive.OfferIncentive(transactor, offer)
fmt.Println("Transaction hash:", tx.Hash().Hex())
time.Sleep(3000 * time.Millisecond)
// Get the new sample size increase price, sample size, range, and scale
sampleSizeIncreasePrice, _ = incentive.GetCurrentSampleSizeIncreasePrice(opts)
expectedSampleSize, _ = incentive.GetExpectedSampleSize(opts)
rangeVal, _ = incentive.GetRange(opts)
scale, _ = incentive.GetScale(opts)
fmt.Println("Sample Size Increase Price:", sampleSizeIncreasePrice)
fmt.Println("Current Sample Size:", expectedSampleSize)
fmt.Println("Current Range:", rangeVal)
fmt.Println("Current Scale:", scale)
}