Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: rewards v2 calculation #120

Draft
wants to merge 2 commits into
base: rajath/rewards-calculation
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions pkg/rewards/7_goldActiveODRewards.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package rewards

import (
"database/sql"

"go.uber.org/zap"
)

var _7_goldActiveODRewardsQuery = `
create table {{.destTableName}} as
WITH od_rewards_with_block_info as (
select
odrs.avs,
odrs.reward_hash,
odrs.token,
odrs.operator,
odrs.operator_index,
odrs.amount,
odrs.strategy,
odrs.strategy_index,
odrs.multiplier,
odrs.start_timestamp::timestamp(6),
odrs.end_timestamp::timestamp(6),
odrs.duration,
odrs.block_number,
b.block_time::timestamp(6),
to_char(b.block_time, 'YYYY-MM-DD') AS block_date,
from operator_directed_reward_submissions as odrs
left join blocks as b on (b.number = odrs.block_number)
where b.block_time < TIMESTAMP '{{.cutoffDate}}'
),
active_rewards_modified as (
SELECT *,
amount/(duration/86400) as tokens_per_day,
cast(@cutoffDate AS TIMESTAMP(6)) as global_end_inclusive -- Inclusive means we DO USE this day as a snapshot
FROM od_rewards_with_block_info
WHERE end_timestamp >= TIMESTAMP '{{.rewardsStart}}' and start_timestamp <= TIMESTAMP '{{.cutoffDate}}'
),
-- Cut each reward's start and end windows to handle the global range
active_rewards_updated_end_timestamps as (
SELECT
avs,
operator,
/**
* Cut the start and end windows to handle
* A. Retroactive rewards that came recently whose start date is less than start_timestamp
* B. Don't make any rewards past end_timestamp for this run
*/
start_timestamp as reward_start_exclusive,
LEAST(global_end_inclusive, end_timestamp) as reward_end_inclusive,
tokens_per_day,
token,
multiplier,
strategy,
reward_hash,
global_end_inclusive,
block_date as reward_submission_date
FROM active_rewards_modified
),
-- For each reward hash, find the latest snapshot
active_rewards_updated_start_timestamps as (
SELECT
ap.avs,
ap.operator,
COALESCE(MAX(g.snapshot), ap.reward_start_exclusive) as reward_start_exclusive,
-- ap.reward_start_exclusive,
ap.reward_end_inclusive,
ap.token,
-- We use floor to ensure we are always underesimating total tokens per day
floor(ap.tokens_per_day) as tokens_per_day_decimal,
-- Round down to 15 sigfigs for double precision, ensuring know errouneous round up or down
ap.tokens_per_day * ((POW(10, 15) - 1)/(POW(10, 15))) as tokens_per_day,
ap.multiplier,
ap.strategy,
ap.reward_hash,
ap.global_end_inclusive,
ap.reward_submission_date
FROM active_rewards_updated_end_timestamps ap
LEFT JOIN gold_table g ON g.reward_hash = ap.reward_hash
GROUP BY ap.avs, ap.operator, ap.reward_end_inclusive, ap.token, ap.tokens_per_day, ap.multiplier, ap.strategy, ap.reward_hash, ap.global_end_inclusive, ap.reward_start_exclusive, ap.reward_submission_date
),
-- Parse out invalid ranges
active_reward_ranges AS (
SELECT * from active_rewards_updated_start_timestamps
/** Take out (reward_start_exclusive, reward_end_inclusive) windows where
* 1. reward_start_exclusive >= reward_end_inclusive: The reward period is done or we will handle on a subsequent run
*/
WHERE reward_start_exclusive < reward_end_inclusive
),
-- Explode out the ranges for a day per inclusive date
exploded_active_range_rewards AS (
SELECT
*
FROM active_reward_ranges
CROSS JOIN generate_series(DATE(reward_start_exclusive), DATE(reward_end_inclusive), INTERVAL '1' DAY) AS day
),
active_rewards_final AS (
SELECT
avs,
operator,
cast(day as DATE) as snapshot,
token,
tokens_per_day,
tokens_per_day_decimal,
multiplier,
strategy,
reward_hash,
reward_submission_date
FROM exploded_active_range_rewards
-- Remove snapshots on the start day
WHERE day != reward_start_exclusive
)
select * from active_rewards_final
`

// Generate7ActiveODRewards generates active operator-directed rewards for the gold_7_active_od_rewards table
//
// @param snapshotDate: The upper bound of when to calculate rewards to
// @param startDate: The lower bound of when to calculate rewards from. If we're running rewards for the first time,
// this will be "1970-01-01". If this is a subsequent run, this will be the last snapshot date.
func (r *RewardsCalculator) Generate7ActiveODRewards(snapshotDate string) error {
allTableNames := getGoldTableNames(snapshotDate)
destTableName := allTableNames[Table_7_ActiveODRewards]

rewardsStart := "1970-01-01 00:00:00" // This will always start as this date and get's updated later in the query

r.logger.Sugar().Infow("Generating active rewards",
zap.String("rewardsStart", rewardsStart),
zap.String("cutoffDate", snapshotDate),
zap.String("destTableName", destTableName),
)

query, err := renderQueryTemplate(_7_goldActiveODRewardsQuery, map[string]string{
"destTableName": destTableName,
"rewardsStart": rewardsStart,
"cutoffDate": snapshotDate,
})
if err != nil {
r.logger.Sugar().Errorw("Failed to render query template", "error", err)
return err
}

res := r.grm.Exec(query,
sql.Named("cutoffDate", snapshotDate),
)
if res.Error != nil {
r.logger.Sugar().Errorw("Failed to generate active od rewards", "error", res.Error)
return res.Error
}
return nil
}
45 changes: 29 additions & 16 deletions pkg/rewards/rewards.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ func (rc *RewardsCalculator) generateGoldTables(snapshotDate string) error {
return err
}

if err := rc.Generate7ActiveODRewards(snapshotDate); err != nil {
rc.logger.Sugar().Errorw("Failed to generate active od rewards", "error", err)
return err
}

if err := rc.GenerateGold7StagingTable(snapshotDate); err != nil {
rc.logger.Sugar().Errorw("Failed to generate gold staging", "error", err)
return err
Expand Down Expand Up @@ -394,25 +399,33 @@ func (rc *RewardsCalculator) generateAndInsertFromQuery(
}

var (
Table_1_ActiveRewards = "gold_1_active_rewards"
Table_2_StakerRewardAmounts = "gold_2_staker_reward_amounts"
Table_3_OperatorRewardAmounts = "gold_3_operator_reward_amounts"
Table_4_RewardsForAll = "gold_4_rewards_for_all"
Table_5_RfaeStakers = "gold_5_rfae_stakers"
Table_6_RfaeOperators = "gold_6_rfae_operators"
Table_7_GoldStaging = "gold_7_staging"
Table_8_GoldTable = "gold_table"
Table_1_ActiveRewards = "gold_1_active_rewards"
Table_2_StakerRewardAmounts = "gold_2_staker_reward_amounts"
Table_3_OperatorRewardAmounts = "gold_3_operator_reward_amounts"
Table_4_RewardsForAll = "gold_4_rewards_for_all"
Table_5_RfaeStakers = "gold_5_rfae_stakers"
Table_6_RfaeOperators = "gold_6_rfae_operators"
Table_7_ActiveODRewards = "gold_7_active_od_rewards"
Table_8_StakerODRewardAmounts = "gold_8_staker_od_reward_amounts"
Table_9_OperatorODRewardAmounts = "gold_9_operator_od_reward_amounts"
Table_10_AvsODRewardAmounts = "gold_10_avs_od_reward_amounts"
Table_7_GoldStaging = "gold_7_staging"
Table_8_GoldTable = "gold_table"
)

var goldTableBaseNames = map[string]string{
Table_1_ActiveRewards: "gold_1_active_rewards",
Table_2_StakerRewardAmounts: "gold_2_staker_reward_amounts",
Table_3_OperatorRewardAmounts: "gold_3_operator_reward_amounts",
Table_4_RewardsForAll: "gold_4_rewards_for_all",
Table_5_RfaeStakers: "gold_5_rfae_stakers",
Table_6_RfaeOperators: "gold_6_rfae_operators",
Table_7_GoldStaging: "gold_7_staging",
Table_8_GoldTable: "gold_table",
Table_1_ActiveRewards: "gold_1_active_rewards",
Table_2_StakerRewardAmounts: "gold_2_staker_reward_amounts",
Table_3_OperatorRewardAmounts: "gold_3_operator_reward_amounts",
Table_4_RewardsForAll: "gold_4_rewards_for_all",
Table_5_RfaeStakers: "gold_5_rfae_stakers",
Table_6_RfaeOperators: "gold_6_rfae_operators",
Table_7_ActiveODRewards: "gold_7_active_od_rewards",
Table_8_StakerODRewardAmounts: "gold_8_staker_od_reward_amounts",
Table_9_OperatorODRewardAmounts: "gold_9_operator_od_reward_amounts",
Table_10_AvsODRewardAmounts: "gold_10_avs_od_reward_amounts",
Table_7_GoldStaging: "gold_7_staging",
Table_8_GoldTable: "gold_table",
}

func getGoldTableNames(snapshotDate string) map[string]string {
Expand Down
Loading