Skip to content

Commit

Permalink
Merge branch 'rewards-208' into 'main'
Browse files Browse the repository at this point in the history
fix for fast updates, rewards 208

See merge request flarenetwork/ftso-scaling!110
  • Loading branch information
alenabelium committed Jul 22, 2024
2 parents 780d0dc + 8262767 commit a3ce6a5
Show file tree
Hide file tree
Showing 10 changed files with 6,413 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export async function fullRoundOfferCalculation(options: OptionalCommandOptions)
const fuRewardOfferMap: Map<
number,
Map<string, IFUPartialRewardOfferForRound[]>
> = granulatedPartialOfferMapForFastUpdates(rewardEpochInfo);
> = granulatedPartialOfferMapForFastUpdates(rewardEpochInfo, randomNumbers);
serializeGranulatedPartialOfferMap(rewardEpochDuration, fuRewardOfferMap, false, FU_OFFERS_FILE);
}
}
Expand Down
5 changes: 3 additions & 2 deletions libs/ftso-core/src/reward-calculation/reward-calculation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,11 @@ export async function partialRewardClaimsForVotingRound(
}
const fuFeedValueMap = new Map<string, FUFeedValue>();
if (
rewardEpochInfo.fuInflationRewardsOffered.feedConfigurations.length !== data.fastUpdatesData.feedValues.length
rewardEpochInfo.fuInflationRewardsOffered.feedConfigurations.length > data.fastUpdatesData.feedValues.length
) {
throw new Error("Critical error: Feed configurations and feed values do not match");
throw new Error("Critical error: Feed configurations contain more feeds then feed values");
}
// if new feeds are introduced during the voting round, they are ignored
for (let i = 0; i < rewardEpochInfo.fuInflationRewardsOffered.feedConfigurations.length; i++) {
const feedConfiguration = rewardEpochInfo.fuInflationRewardsOffered.feedConfigurations[i];
const value = data.fastUpdatesData.feedValues[i];
Expand Down
15 changes: 15 additions & 0 deletions libs/ftso-core/src/reward-calculation/reward-fast-updates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ export function calculateFastUpdatesClaims(
signingAddressToFeeBips: Map<Address, number>,
logger: ILogger
): IPartialRewardClaim[] {
if (offer.shouldBeBurned) {
const fullOfferBackClaim: IPartialRewardClaim = {
votingRoundId: offer.votingRoundId,
beneficiary: BURN_ADDRESS,
amount: offer.amount,
claimType: ClaimType.DIRECT,
offerIndex: 0,
// feedId: offer.feedId, // should be undefined
protocolTag: "" + FTSO2_FAST_UPDATES_PROTOCOL_ID,
rewardTypeTag: RewardTypePrefix.FULL_OFFER_CLAIM_BACK,
rewardDetailTag: "", // no additional tag
};
return [fullOfferBackClaim];
}

if (signingPolicyAddressesSubmitted.length === 0 || medianResult.data.finalMedian.isEmpty) {
const backClaim: IPartialRewardClaim = {
votingRoundId: offer.votingRoundId,
Expand Down
62 changes: 37 additions & 25 deletions libs/ftso-core/src/reward-calculation/reward-offers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ export function granulatedPartialOfferMapForRandomFeedSelection(
): Map<number, Map<string, IPartialRewardOfferForRound[]>> {
if (randomNumbers.length !== endVotingRoundId - startVotingRoundId + 1) {
throw new Error(
`Random numbers length ${randomNumbers.length} does not match voting rounds length ${
endVotingRoundId - startVotingRoundId + 1
`Random numbers length ${randomNumbers.length} does not match voting rounds length ${endVotingRoundId - startVotingRoundId + 1
}`
);
}
Expand Down Expand Up @@ -166,8 +165,7 @@ export function fixOffersForRandomFeedSelection(
) {
if (randomNumbers.length !== endVotingRoundId - startVotingRoundId + 1) {
throw new Error(
`Random numbers length ${randomNumbers.length} does not match voting rounds length ${
endVotingRoundId - startVotingRoundId + 1
`Random numbers length ${randomNumbers.length} does not match voting rounds length ${endVotingRoundId - startVotingRoundId + 1
}`
);
}
Expand Down Expand Up @@ -232,13 +230,21 @@ export function splitRewardOfferByTypes<T extends IPartialRewardOfferForEpoch>(o
}

export function granulatedPartialOfferMapForFastUpdates(
rewardEpochInfo: RewardEpochInfo
rewardEpochInfo: RewardEpochInfo,
randomNumbers: (bigint | undefined)[],
): Map<number, Map<string, IFUPartialRewardOfferForRound[]>> {
const startVotingRoundId = rewardEpochInfo.signingPolicy.startVotingRoundId;
const endVotingRoundId = rewardEpochInfo.endVotingRoundId;
if (startVotingRoundId === undefined || endVotingRoundId === undefined) {
throw new Error("Start or end voting round id is undefined");
}
if (randomNumbers.length !== endVotingRoundId - startVotingRoundId + 1) {
throw new Error(
`Random numbers length ${randomNumbers.length} does not match voting rounds length ${endVotingRoundId - startVotingRoundId + 1
}`
);
}

// Calculate total amount of rewards for the reward epoch
let totalAmount = rewardEpochInfo.fuInflationRewardsOffered.amount;

Expand All @@ -256,27 +262,33 @@ export function granulatedPartialOfferMapForFastUpdates(
const remainder: number = Number(totalAmount % BigInt(numberOfVotingRounds));

for (let votingRoundId = startVotingRoundId; votingRoundId <= endVotingRoundId; votingRoundId++) {
let undistributedVotingRoundAmount = sharePerOne + (votingRoundId - startVotingRoundId < remainder ? 1n : 0n);
let totalUndistributedShares = rewardEpochInfo.fuInflationRewardsOffered.feedConfigurations.reduce(
(acc, feed) => acc + BigInt(feed.inflationShare),
0n
);
for (const configuration of rewardEpochInfo.fuInflationRewardsOffered.feedConfigurations) {
const amount = (undistributedVotingRoundAmount * BigInt(configuration.inflationShare)) / totalUndistributedShares;
undistributedVotingRoundAmount -= amount;
totalUndistributedShares -= BigInt(configuration.inflationShare);
const feedOfferForVoting: IFUPartialRewardOfferForRound = {
votingRoundId,
amount,
feedId: configuration.feedId,
rewardBandValue: configuration.rewardBandValue,
};
const feedOffers = rewardOfferMap.get(votingRoundId) || new Map<string, IFUPartialRewardOfferForRound[]>();
rewardOfferMap.set(votingRoundId, feedOffers);
const feedIdOffers = feedOffers.get(configuration.feedId) || [];
feedOffers.set(configuration.feedId, feedIdOffers);
feedIdOffers.push(feedOfferForVoting);
const randomNumber = randomNumbers[votingRoundId - startVotingRoundId];

const selectedFeedIndex =
randomNumber === undefined ? 0 : Number(randomNumber % BigInt(rewardEpochInfo.fuInflationRewardsOffered.feedConfigurations.length));

const selectedFeedConfig = rewardEpochInfo.fuInflationRewardsOffered.feedConfigurations[selectedFeedIndex];
const selectedFeedId = selectedFeedConfig.feedId;
let amount = sharePerOne + (votingRoundId - startVotingRoundId < remainder ? 1n : 0n);

// Create adapted offer with selected feed
const feedOfferForVoting: IFUPartialRewardOfferForRound = {
votingRoundId,
amount,
feedId: selectedFeedId,
rewardBandValue: selectedFeedConfig.rewardBandValue,
};

// Mark offer for full burning
if (randomNumber === undefined) {
feedOfferForVoting.shouldBeBurned = true;
}

const feedOffers = rewardOfferMap.get(votingRoundId) || new Map<string, IFUPartialRewardOfferForRound[]>();
rewardOfferMap.set(votingRoundId, feedOffers);
const feedIdOffers = feedOffers.get(selectedFeedConfig.feedId) || [];
feedOffers.set(selectedFeedConfig.feedId, feedIdOffers);
feedIdOffers.push(feedOfferForVoting);
}
return rewardOfferMap;
}
1 change: 1 addition & 0 deletions libs/ftso-core/src/utils/PartialRewardOffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface IFUPartialRewardOfferForRound {
feedId: string;
amount: bigint;
rewardBandValue: number;
shouldBeBurned?: boolean;
}

export namespace PartialRewardOffer {
Expand Down
Loading

0 comments on commit a3ce6a5

Please sign in to comment.