-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
141 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package rewards | ||
|
||
import ( | ||
"github.com/Layr-Labs/sidecar/pkg/rewardsUtils" | ||
"go.uber.org/zap" | ||
) | ||
|
||
const _9_goldStakerODRewardAmountsQuery = ` | ||
create table {{.destTableName}} as | ||
-- Get the rows where operators have registered for the AVS | ||
WITH reward_snapshot_operators as ( | ||
SELECT | ||
ap.reward_hash, | ||
ap.snapshot as snapshot, | ||
ap.token, | ||
ap.tokens_per_day, | ||
ap.tokens_per_day_decimal, | ||
ap.avs as avs, | ||
ap.operator as operator, | ||
ap.strategy, | ||
ap.multiplier, | ||
ap.reward_submission_date | ||
FROM {{.activeRewardsTable}} ap | ||
JOIN operator_avs_registration_snapshots oar | ||
ON ap.avs = oar.avs and ap.snapshot = oar.snapshot and ap.operator = oar.operator | ||
), | ||
-- Calculate the total staker split for each operator reward with dynamic split logic | ||
-- If no split is found, default to 1000 (10%) | ||
staker_splits AS ( | ||
SELECT rso.*, | ||
rso.tokens_per_day_decimal - FLOOR(rso.tokens_per_day_decimal * COALESCE(oas.split, 1000) / CAST(10000 AS DECIMAL)) as staker_split | ||
FROM reward_snapshot_operators rso | ||
LEFT JOIN operator_avs_split_snapshots oas | ||
ON rso.operator = oas.operator AND rso.avs = oas.avs AND rso.snapshot = oas.snapshot | ||
), | ||
_operator_restaked_strategies AS ( | ||
SELECT | ||
ss.* | ||
FROM staker_splits ss | ||
JOIN operator_avs_strategy_snapshots oas | ||
ON | ||
ss.operator = oas.operator AND | ||
ss.avs = oas.avs AND | ||
ss.strategy = oas.strategy AND | ||
ss.snapshot = oas.snapshot | ||
), | ||
-- Get the stakers that were delegated to the operator for the snapshot | ||
staker_delegated_operators AS ( | ||
SELECT | ||
ors.*, | ||
sds.staker | ||
FROM _operator_restaked_strategies ors | ||
JOIN staker_delegation_snapshots sds | ||
ON | ||
ors.operator = sds.operator AND | ||
ors.snapshot = sds.snapshot | ||
), | ||
-- Get the shares for staker delegated to the operator | ||
staker_avs_strategy_shares AS ( | ||
SELECT | ||
sdo.*, | ||
sss.shares | ||
FROM staker_delegated_operators sdo | ||
JOIN staker_share_snapshots sss | ||
ON | ||
sdo.staker = sss.staker AND | ||
sdo.snapshot = sss.snapshot AND | ||
sdo.strategy = sss.strategy | ||
-- Parse out negative shares and zero multiplier so there is no division by zero case | ||
WHERE sss.shares > 0 and sdo.multiplier != 0 | ||
), | ||
-- Calculate the weight of a staker | ||
staker_weights AS ( | ||
SELECT *, | ||
SUM(multiplier * shares) OVER (PARTITION BY staker, reward_hash, snapshot) AS staker_weight | ||
FROM staker_avs_strategy_shares | ||
), | ||
-- Get distinct stakers since their weights are already calculated | ||
distinct_stakers AS ( | ||
SELECT * | ||
FROM ( | ||
SELECT *, | ||
-- We can use an arbitrary order here since the staker_weight is the same for each (staker, strategy, hash, snapshot) | ||
-- We use strategy ASC for better debuggability | ||
ROW_NUMBER() OVER (PARTITION BY reward_hash, snapshot, staker ORDER BY strategy ASC) as rn | ||
FROM staker_weights | ||
) t | ||
WHERE rn = 1 | ||
ORDER BY reward_hash, snapshot, staker | ||
), | ||
-- Calculate sum of all staker weights for each reward and snapshot | ||
staker_weight_sum AS ( | ||
SELECT *, | ||
SUM(staker_weight) OVER (PARTITION BY reward_hash, snapshot) as total_weight | ||
FROM distinct_stakers | ||
), | ||
-- Calculate staker proportion of tokens for each reward and snapshot | ||
staker_proportion AS ( | ||
SELECT *, | ||
FLOOR((staker_weight / total_weight) * 1000000000000000) / 1000000000000000 AS staker_proportion | ||
FROM staker_weight_sum | ||
), | ||
-- Calculate the staker reward amount | ||
staker_reward_amounts AS ( | ||
SELECT *, | ||
FLOOR(staker_proportion * staker_split) as staker_tokens | ||
FROM staker_proportion | ||
) | ||
SELECT * FROM staker_reward_amounts | ||
` | ||
|
||
func (rc *RewardsCalculator) GenerateGold9StakerODRewardAmountsTable(snapshotDate string) error { | ||
allTableNames := rewardsUtils.GetGoldTableNames(snapshotDate) | ||
destTableName := allTableNames[rewardsUtils.Table_9_StakerODRewardAmounts] | ||
|
||
rc.logger.Sugar().Infow("Generating Staker OD reward amounts", | ||
zap.String("cutoffDate", snapshotDate), | ||
zap.String("destTableName", destTableName), | ||
) | ||
|
||
query, err := rewardsUtils.RenderQueryTemplate(_9_goldStakerODRewardAmountsQuery, map[string]string{ | ||
"destTableName": destTableName, | ||
"activeRewardsTable": allTableNames[rewardsUtils.Table_7_ActiveODRewards], | ||
}) | ||
if err != nil { | ||
rc.logger.Sugar().Errorw("Failed to render query template", "error", err) | ||
return err | ||
} | ||
|
||
res := rc.grm.Exec(query) | ||
if res.Error != nil { | ||
rc.logger.Sugar().Errorw("Failed to create gold_staker_od_reward_amounts", "error", res.Error) | ||
return res.Error | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters