Skip to content

Latest commit

 

History

History
248 lines (180 loc) · 25 KB

README.md

File metadata and controls

248 lines (180 loc) · 25 KB

Reward calculation for FTSOv2

Introduction

The document describes the reward calculation for FTSOv2 that includes both FTSO scaling and FTSO fast updates protocols.

Rewards are calculated for each reward epoch, its duration being 3.5 days. Each reward epoch gets assigned a total reward pool, separately for each of the two protocols. These funds are then distributed to data providers and the community through reward claims, which are essentially the records of who (beneficiary) gets what amount of the reward. Claims are aggregated per beneficiary, packed into Merkle tree which gets signed by majority of the weight of data providers or by governance. Once the reward Merkle root is confirmed, claiming of rewards through RewardManager smart contract is possible.

Total reward pool

From all rewards that are assigned from the inflation to FTSOv2, 70% go to FTSO scaling and 30% to FTSO fast updates protocols. In both protocols all reward funds for a given reward epoch go into a separate but joint pool per protocol. From the total reward pool, each voting round within the reward epoch gets assigned equal share of the total reward (remainder r gets distributed to first r voting rounds). All reward calculations are done per each protocol and per each voting round separately.

FTSO Scaling protocol

Reward funds for a given reward epoch for FTSO scaling protocol come from:

  • inflation,
  • community reward offers. Any user can require a new feed by sending a reward offer prior to the start of a reward epoch. Substantial minimal amount is required for the reward offer.

FTSO fast updates protocol

Reward funds for FTSO fast updates come from:

  • inflation,
  • community incentives to increase volatility.

Secure reward random number

FTSO scaling protocol generates a random number for each voting round. The random number may be secure or not. For the purpose of reward calculation, we assign to each voting round a secure reward random number which is defined as the earliest secure random number generated by the protocol in the subsequent voting rounds. For example, consider voting round N. Then usually a secure random number is obtained from the voting round N + 1, say r. Then the secure reward random number for the voting round N is sha256(r, N). Note that it may happen that the first secure random number occurs only in the voting round e.g. N+5, say s. That secure random number is then used for determining the secure reward random numbers of voting rounds N, N + 1, ..., N + 4, as sha256(s, N), sha256(s, N + 1), ..., sha256(s, N + 4), respectively.

Note that for the voting rounds at the end of the reward epoch R a lookup into random numbers generated in the voting rounds at the beginning of the next reward epoch R + 1 is needed. That lookup is limited to at most 30 voting rounds. Note that if only one (the first) of the generated random numbers in those 30 voting rounds is secure, then the last voting round of R can get assigned the rewarding random number. In the extreme case that all 30 generated random numbers are not secure, the last voting round of reward epoch R (and possibly few previous) may not get assigned the secure reward random number. In this case all the funds for rewarding in those voting rounds get burned.

Rewarded feed choice

Only one feed is rewarded in each voting round. The feed is chosen by using the reward random number assigned to the voting round. Note that during the voting round the assigned secure random number is not known in advance hence data providers cannot speculate on which feed in the voting round will be rewarded and they have to compete on all feeds.

FTSO Scaling reward calculation in a voting round

The total reward amount for the voting round is split into 3 parts:

  • 80% goes to accuracy rewarding (closeness to median),
  • 10% goes to correct and timely signature submission rewarding,
  • 10% goes to finalization rewarding.

In addition to distributed rewards, penalizations for malicious behavior are implemented. There are two types of penalizations:

  • Reveal offending: A commit not followed by a reveal, or followed by an invalid reveal, impacts the system negatively and will be considered a reveal offense.
  • Double-signing: Sending signatures for different results in the same voting round will be considered double-signing. Note that signing (only once) a wrong thing or providing wrongly formatted signatures is not penalized.

In both cases, the penalty is 30 times the offending data provider’s expected relative share of rewards in that voting round, and it is deducted from the total amount of rewards at the end of the reward epoch. The maximum amount that can be deducted is equal to the data provider’s total reward in the epoch. The deducted amount is burned. If penalties exceed the earned rewards, the data provider gets no reward. Penalties apply to total data provider’s earnings, hence both on fees and the share of rewards that goes to the community of the delegators.

Accuracy rewarding (80%)

Accuracy rewarding consists of two parts:

  • 70% of the accuracy rewards are assigned to the primary reward band, defined as the weighted interquartile range (IQR) around the median value determined for that round. Capped delegation weights are used for reward distribution where the cap is set to 2.5% of WFLR supply. A data provider is considered to be in IQR for a given voting round if (1) its price is strictly within the IQR range, or (2) if its price is on one of the boundaries of the IQR, then it is included with probability of 50%. Sum of the capped weights of data providers constitutes the total rewarded weight. Providers considered to be within this IQR band receive a proportion of these rewards equal to their capped weight, relative to the total rewarded weight. For example, if a provider has 2.5% of the total voter’s weight, and 50% of all data provider weight lies within the IQR, the successful provider will receive 5% (2.5/50) of the reward for this band.
  • 30% of accuracy rewards are assigned to the secondary band. This band has a fixed percentage width around the median value for the round, intending to reward providers whose estimates are close to the median, but not competitive enough to lie within the IQR. Providers whose estimates lie strictly within this band receive a proportion of these rewards equal to their weight, relative to the total weight of providers whose estimate lies strictly within the percentage band. For example, if 75% of provider weight lies strictly within the percentage band, and a successful provider has 2.5% of the total weight, they receive 3.3% (=2.5/75) of the reward for this band.

Note that it can happen in some special cases that no voter is in any of the bands or a prescribed turnout of voters is too low for the rewarded feed. In this case all funds for accuracy rewards are burned and no data providers get accuracy rewards for the voting round. Low turnout threshold is specified for each feed in reward offers. If this happens the reward funds are burned for that voting round.

Correct and timely signing rewarding (10%)

Providers who submit a signature for the consensus Merkle root in due time, and have received non-zero reward from accuracy rewarding (see above) are eligible for this part of the reward. A provider is considered to have submitted in due time if (1) the submission was done in the signature submission grace period, which ends 10s after the end of reveals, or (2) before the first finalization of the consensus Merkle root. A provider receives a share of the reward equal to their weight as a proportion of the weight of providers who are eligible for this reward.

When calculating rewards, a Merkle root for voting round N is considered to be the consensus Merkle root if it happens to be signed by 50%+ of data providers’ signing weight and finalization takes place before the end of the voting epoch N + 1. In case this does not happen (at all, or the finalization is done beyond voting epoch N + 1) the consensus Merkle root is considered as unknown (for rewarding purposes). Then the rewards are still distributed among the signers that have signed some Merkle root before the end of voting epoch N + 1 and that Merkle root got the biggest support in terms of the signing weight.

Prompt finalizing rewarding (10%)

Each round, a handful of providers are randomly allocated the opportunity to finalize the round, with probability relative to their signing weight (which is usually different from delegation weight!). A subset of those chosen providers that receives non-negative reward from the accuracy part (see above), is considered as eligible finalizers. If F denotes the number of eligible (selected) finalizers, then each eligible finalizer promptly finalizing the round receives a 1/F-th share of the finalization reward. If none of these providers complete finalization of the round sufficiently promptly, it is opened up to all users of the Flare network, with the first one who finalizes the round claiming the total amount of the available reward for the voting round. The window for selected data providers to get the reward is called the finalization grace period and ends 20s after the reveal deadline.

Fast updates calculation in a voting round

Fast updates are assigned 30% of the rewards for a round of the FTSOv2, with reward determined every 90 seconds (per voting epoch), in line with the FTSO scaling cadency. Each block, a number of providers are randomly chosen to provide fast updates, with probability proportional to their weight. The rewards are assigned at the end of the 90 second round to those providers who have submitted updates, depending on the following criteria.

Total reward for voting round is distributed according to the accuracy as follows:

  • At the end of the 90 second round, the value of the fast update stream is compared to the FTSO scaling median price. Assuming that it is suitably close to the median price, the Fast Update accuracy rewards for the round are awarded.
  • These rewards are assigned to each provider who has given an update in the 90s period, with each provider receiving a share relative to the amount of updates they have given in the round (or equally - each update gets the same share of rewards).
  • If in some voting round there are no updates or accuracy is not sufficient, the reward intended for the voting round is burned.

Reward claims

Reward claims are records of a part of a reward (or penalization) assignment. There are aggregated reward claims and detailed reward claims. The reward calculation process creates detailed reward claims for each separate component of rewarding in each voting round. The claims for parts of rewards are positive, while the penalization claims are negative. Note that the sum of all positive (non-penalization) claims matches the total reward fund. Aggregated reward claims are obtained by aggregating the detailed reward claims by beneficiary and claim type (see below).

Detailed reward claims

Detailed reward claims are records containing the following fields:

  • votingRoundId - voting round id for which the claim is calculated.
  • beneficiary - address or node id of the beneficiary of the claim. The interpretation (whether it is an address or node id) of the field depends on the claimType.
  • claimType - type of the claim, one of the following:
    • 0 - DIRECT - a direct reward claim to an address.
    • 1 - FEE - the reward claim represents the fee of a data provider. In this case beneficiary field is the identity address of a data provider who gets the fee.
    • 2 - WNAT - the reward claim represents the part of the reward earned by the data provider that gets distributed to the community of delegators. The beneficiary field is the delegation address of the data provider.
    • 3 - MIRROR - the reward claim represents the part of the reward earned by the data provider that gets distributed to the community of stakers and stake delegators on the nodes that belong to the data provider. This is relevant only on Coston2 and Flare networks. The beneficiary is the relevant node id (encoded into 20-byte code) on which the stakes that get the reward amount are provided.
    • 4 - CCHAIN - not used, possible future use.
  • amount - amount of the claim.
  • offerIndex - reference to inflation or community offer from which the reward comes. Not relevant.
  • feedId - feed, if relevant, from which currency the claim was generated, in particular which currency was chosen for the specific voting round.
  • protocolTag - see below.
  • rewardTypeTag - see below.
  • rewardDetailTag - see below.

Reward claim classification

The reward claims are marked with three tags:

  • protocolTag
  • rewardTypeTag
  • rewardDetailTag

Protocol tag

Possible values of protocolTag are:

  • 100 - Indicates FTSO scaling protocol.
  • 255 - FTSO fast updates protocol.

Reward type tag

Reward type tag indicates which component of rewarding or penalization in relevant protocol participated in the reward claim. The options are as follows:

  • Median - accuracy reward claim for FTSO scaling.
  • Signing - timely signing reward claim for FTSO scaling.
  • Finalization - prompt finalization reward for FTSO scaling.
  • Double signers - penalization for double signing in FTSO scaling protocol.
  • Reveal offenders - penalization for reveal offenders in FTSO scaling protocol.
  • Fast updates accuracy - accuracy reward for FAST updates protocol.
  • Full offer claim back - full reward offer burning/claim back in FTSO scaling protocol. Happens when a voting round does not receive a secure reward random number and the rewarded feed cannot be chosen. Consequently, this is a reward claim to claim to the burn address. Detail tags are irrelevant in this case and are empty.

Reward detail tag

Reward detail tag depends on reward type tag. Hence both tags constitute a two level hierarchical tagging.

For Median

These detail tags appear only in claims generated FTSO scaling protocol rewarding, when the reward type tag is Median.

  • LOW_TURNOUT_CLAIM_BACK - the weight that participated in the weighted median algorithm is too low compared to the total voting weight. This makes this claim to be burned (assigned to claim back address).
  • NO_NORMALIZED_WEIGHT - a weight normalization is calculated to avoid fractions during the distribution of the rewards for primary and secondary bands. If the total normalized weight is 0, then the burn claim with this tag is generated.
  • FEE - fee part of the accuracy reward. The beneficiary of such a claim is the identity address of the data provider.
  • PARTICIPATION - the major part of the accuracy reward which is assigned to the community of delegators.

Reward distribution according to signing weight

When rewards are distributed with reward type tags Signing and Finalization to a specific voter, the following detail tags can appear.

  • NO_VOTER_WEIGHT - extreme case where a data provider has zero total weight but should receive some reward. In this case the claim gets burned (beneficiary is burn or claim back address). Claim type is DIRECT.
  • FEE_FOR_DELEGATION_AND_STAKING - fee claim for data provider, beneficiary is data provider’s identity address. Claim type is FEE.
  • DELEGATION_COMMUNITY_REWARD - claim for a part of the signing weight of a data provider obtained from delegations. The beneficiary is the delegation address of the data provider. Claim type is WNAT.
  • NODE_COMMUNITY_REWARD - claim for a part of the signing weight of a data provider obtained from stakes. The beneficiary is the node id encoded into 20-bytes of a node assigned to a data provider. Claim type is MIRROR.

For Signing

In case some parts of funds intended for correct signing and signature deposition get burned, one of the following detail tags are used.

  • NO_MOST_FREQUENT_SIGNATURES - In case that finalization for the voting round N is not done by the end of the voting epoch N + 1 and there are no signatures the burn claim is generated.
  • NO_WEIGHT_OF_ELIGIBLE_SIGNERS - eligible signers (the ones that earned non-zero reward from accuracy part) have total weight 0.
  • CLAIM_BACK_DUE_TO_NON_ELIGIBLE_SIGNER - reward claim for a non-eligible signer in a voting round is burned and marked with this tag.
  • CLAIM_BACK_NO_CLAIMS - if there are no reward claims by eligible signers, the remaining funds get burned and marked with this tag.

For Finalization

When finalizing the following reward detail tags are used.

  • NO_FINALIZATION - no finalization was done for the voting round N before the end of the voting epoch N + 1. The burn claim is generated.
  • OUTSIDE_OF_GRACE_PERIOD - the first finalization was done outside the grace period for finalization (end of reveal + 20s) and the address that did the finalization gets full finalization reward claim marked by this tag.
  • FINALIZED_BUT_NO_ELIGIBLE_VOTERS - the finalization was done during the grace period for finalization but by a non-eligible voter, while on the other hand there were no eligible finalizers submitting valid finalization data during the grace period. Hence the burn claim is generated.
  • CLAIM_BACK_FOR_UNDISTRIBUTED_REWARDS - a joint burn claim for remaining funds for rewarding prompt finalizing. E.g. some of data providers selected for finalization did not submit the finalization data or became non-eligible due to 0 accuracy rewards.

Fast updates accuracy

Detail tags relevant for FTSOv2 fast updates sub protocol (not FTSO scaling).

  • NO_SUBMISSIONS - no fast updates submissions during the voting epoch so nobody is eligible for rewards. A burn claim is generated.
  • NO_MEDIAN_PRICE - FTSO scaling protocol did not produce a median price so comparison with fast updates price is not possible, hence the burn claim is generated.
  • MISSED_BAND - burn claim for total voting round rewards, when the benchmark fast update price misses the prescribed band around the FTSO scaling price for specific voting round.
  • FEE - fee part of the reward claim of a data provider
  • PARTICIPATION - community reward for delegators earned by a data provider

Calculation data

Public reward data are stored in folders rewards-data/<network>/<rewardEpochId>.

Detailed reward calculation data can be obtained using reward calculation scripts.

  • coston-db.sh
  • songbird-db.sh
  • flare-db.sh The data is calculated into the folder calculations. For each reward epoch rewardEpochId the data are stored into the folder calculations/<rewardEpochId> and within that folder the specific data for each voting round (votingRoundId) are stored in the folders calculations/<rewardEpochId>/<votingRoundId>.

Public reward data

Data calculated by Flare Newtworks are published on https://github.com/flare-foundation/fsp-rewards. Public reward data includes the following files:

  • reward-epoch-info.json - extracted data about reward epoch (offers, signing policy, feeds, boundaries, etc.).
  • reward-distribution-data.json - all aggregated reward claims in the order as they are put into the Merkle tree, together with Merkle proofs and all pieces of data that are necessary to reconstruct the Merkle tree (one can use MerkleTree.ts lib).
  • reward-distribution-data-tuples.json - Same as reward-distribution-data.json, only that reward claims with proofs are encoded as tuples instead of JSON-like structs. This is useful for claiming using the blockchain explorer interface.

Detailed reward calculation data

The detailed data includes the following files.

In folder calculations/<rewardEpochId>:

  • reward-epoch-info.json - see above (the only difference is that big numbers are serialized as "123n" instead "123")
  • reward-distribution-data.json- see above (the only difference is that big numbers are serialized as "123n" instead "123")
  • final-reward-claims.json - final list of claims.
  • calculation-status.json - status file about on-going reward calculation.
  • several *-progress.json files for intermediate (during calculation) progress monitoring

In folders calculations/<rewardEpochId>/<votingRoundId>:

  • reward-calculation-data.json - majority of data that is needed as the input into reward claim calculation.
  • offers.json - partial offers (usually just one) holding total reward funds for the voting round in FTSO scaling protocol.
  • fast-updates-offers.json - partial offers for FTSO fast updates protocol
  • feed-values.json - Merkle tree data with proofs for price feeds and random.
  • claims.json - detailed reward claims for the voting round. Include the claims from both protocols.
  • aggregated-claims.json - aggregated partial claims from previous voting rounds and claims.json.

Claiming rewards

Claiming is done using the function claim(...) on RewardManager smart contract. Delegators and stake delegators can use the claim function without any proofs, once somebody (usually this is done by a dedicated bot, but it may be done essentially by anyone) initializes all the reward claims of claim type 2-WNAT and 3-MIRROR (the latter is relevant on Flare and Coston2 only). Initialization is done using (multiple) calls of function initialiseWeightBasedClaims(...). Once all the proofs of those types of claims for some reward epoch id are initialized, claiming without proofs by delegators and stake delegators are enabled for that reward epoch id. Note that such claims actually claim all the rewards for the reward owner address, also unclaimed rewards from previous reward epochs, up to the claimed one.

On the other hand, data providers wanting to get their fees (claim type 1-FEE and direct claims 0-DIRECT) need to provide an array of claims with Merkle proofs as the last parameter of claim(...) function.

On the explorers, function 4. claim can be used:

In case a new version of the explorer is used, data from reward-distribution-data.json can be entered into interface that allows input per struct fields. In the older version of the explorer the claims with Merkle proofs structs should be encoded as array tuples. Such encoding that can be immediately used in explorer interface is provided in files reward-distribution-data-tuples.json. For example:

Consider the following file songbird/196/reward-distribution-data-tuples.json in the reward publication repository. The first tuple-encoded claim in the array under the key rewardClaims looks like this:

[
  [
    "0xda8b514526d9ac79c13c1f63226c5c1b27b368ff6852b64a5f03ba7a56ffec5c",
    "0x5c56e5f93353a52dca455ad173db2650b226ede83cd523c6218627b2eb610847",
    "0x969000b68be46a0202be7b46b0e637e7e154b3520f7e4c2a0f44b1bfda58e71c",
    "0x7f8415ae69b13b6d951be847c480719cebe22540daccc50845b44c5de2bfbb74",
    "0xccdc296a1d3cbfe55ee55655212dafda624cec02f6f18eb0ec5d678269dd551a",
    "0x0f5b21a211c8acb954e5a63f76374eef4edb4443315167b89f4455581c0cc0f4",
    "0x9592cc6d8d016de2f0c324cbb6ca670c1dc5e71d2bf3bfacaabd68222c2729f3"
  ],
  [
    196,
    "0xee6f6572cfeb3467ce5f3572bea7c5fd6d2b1725",
    "9472868282415650382450",
    1
  ]
]

The following parameters should be provided:

  • _rewardOwner - beneficiary in the list of _proofs.
  • _recipient - any address.
  • _rewardEpochId - reward epoch id as in _proofs.
  • _wrap - option to directly wrap the reward to WFLR (WSGB) on the beneficiary account.
  • _proofs - an array of proofs encoded as tuples (see above). For example, if using one proof as above, one has to wrap it in additional brackets indicating an array (like [...] where the tuple encoded proof should be used instead of ...).

Note that each direct or fee claim is independent. Hence, for example, one can freely first claim the rewards from later reward epoch and then for earlier. Once a specific claim is paid out, it cannot be used anymore to receive a reward.