Skip to content

Commit fdfb4ce

Browse files
committed
fix(rewards): address v2.2 audit findings
- Table 16: use slashing-adjusted base for staker split calculation - Table 17/20: evaluate refunds per operator-set/operator, not per-snapshot - operatorShareSnapshots: apply allocations to all backfill days, include cutoff snapshot
1 parent fcd56e3 commit fdfb4ce

File tree

3 files changed

+22
-10
lines changed

3 files changed

+22
-10
lines changed

pkg/rewards/17_goldAvsOperatorSetUniqueStakeRewards.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,20 @@ WITH total_available_tokens AS (
2323
GROUP BY reward_hash, snapshot, token, avs, operator_set_id, operator
2424
),
2525
26-
-- Step 2: Calculate total tokens actually distributed from the operator rewards table
26+
-- Step 2: Calculate total tokens actually distributed per operator from the operator rewards table
2727
total_distributed_tokens AS (
2828
SELECT
2929
reward_hash,
3030
snapshot,
31+
avs,
32+
operator_set_id,
33+
operator,
3134
COALESCE(SUM(operator_tokens), 0) as distributed_tokens
3235
FROM {{.operatorRewardsTable}}
33-
GROUP BY reward_hash, snapshot
36+
GROUP BY reward_hash, snapshot, avs, operator_set_id, operator
3437
),
3538
36-
-- Step 3: Identify snapshots where distributed tokens = 0, refund all available tokens to AVS
39+
-- Step 3: Identify operator-sets where distributed tokens = 0, refund those tokens to AVS
3740
snapshots_requiring_refund AS (
3841
SELECT
3942
tat.reward_hash,
@@ -47,6 +50,9 @@ snapshots_requiring_refund AS (
4750
LEFT JOIN total_distributed_tokens tdt
4851
ON tat.reward_hash = tdt.reward_hash
4952
AND tat.snapshot = tdt.snapshot
53+
AND tat.avs = tdt.avs
54+
AND tat.operator_set_id = tdt.operator_set_id
55+
AND tat.operator = tdt.operator
5056
WHERE COALESCE(tdt.distributed_tokens, 0) = 0
5157
)
5258

pkg/rewards/20_goldAvsOperatorSetTotalStakeRewards.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,20 @@ WITH total_available_tokens AS (
2323
GROUP BY reward_hash, snapshot, token, avs, operator_set_id, operator
2424
),
2525
26-
-- Step 2: Calculate total tokens actually distributed from the operator rewards table
26+
-- Step 2: Calculate total tokens actually distributed per operator from the operator rewards table
2727
total_distributed_tokens AS (
2828
SELECT
2929
reward_hash,
3030
snapshot,
31+
avs,
32+
operator_set_id,
33+
operator,
3134
COALESCE(SUM(operator_tokens), 0) as distributed_tokens
3235
FROM {{.operatorRewardsTable}}
33-
GROUP BY reward_hash, snapshot
36+
GROUP BY reward_hash, snapshot, avs, operator_set_id, operator
3437
),
3538
36-
-- Step 3: Identify snapshots where distributed tokens = 0, refund all available tokens to AVS
39+
-- Step 3: Identify operator-sets where distributed tokens = 0, refund those tokens to AVS
3740
snapshots_requiring_refund AS (
3841
SELECT
3942
tat.reward_hash,
@@ -47,6 +50,9 @@ snapshots_requiring_refund AS (
4750
LEFT JOIN total_distributed_tokens tdt
4851
ON tat.reward_hash = tdt.reward_hash
4952
AND tat.snapshot = tdt.snapshot
53+
AND tat.avs = tdt.avs
54+
AND tat.operator_set_id = tdt.operator_set_id
55+
AND tat.operator = tdt.operator
5056
WHERE COALESCE(tdt.distributed_tokens, 0) = 0
5157
)
5258

pkg/rewards/operatorShareSnapshots.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ operator_share_windows as (
3030
SELECT
3131
operator, strategy, shares, snapshot_time as start_time,
3232
CASE
33-
-- If the range does not have the end, use the current timestamp truncated to 0 UTC
34-
WHEN LEAD(snapshot_time) OVER (PARTITION BY operator, strategy ORDER BY snapshot_time) is null THEN date_trunc('day', TIMESTAMP '{{.cutoffDate}}')
33+
-- If the range does not have the end, use cutoff + 1 day to include cutoff date snapshot
34+
WHEN LEAD(snapshot_time) OVER (PARTITION BY operator, strategy ORDER BY snapshot_time) is null THEN date_trunc('day', TIMESTAMP '{{.cutoffDate}}') + INTERVAL '1' day
3535
ELSE LEAD(snapshot_time) OVER (PARTITION BY operator, strategy ORDER BY snapshot_time)
3636
END AS end_time
3737
FROM snapshotted_records
@@ -51,15 +51,15 @@ base_snapshots as (
5151
CROSS JOIN
5252
generate_series(DATE(start_time), DATE(end_time) - interval '1' day, interval '1' day) AS day
5353
),
54-
-- Add operator allocations (deallocation delay handled via effective_block)
54+
-- Add operator allocations for all days in the generated window
5555
allocation_adjustments as (
5656
SELECT
5757
oas.operator,
5858
oas.strategy,
5959
SUM(oas.magnitude) as total_magnitude,
6060
oas.snapshot
6161
FROM operator_allocation_snapshots oas
62-
WHERE oas.snapshot = DATE '{{.snapshotDate}}'
62+
WHERE oas.snapshot < DATE '{{.snapshotDate}}'
6363
GROUP BY oas.operator, oas.strategy, oas.snapshot
6464
),
6565
combined_snapshots as (

0 commit comments

Comments
 (0)