-
Notifications
You must be signed in to change notification settings - Fork 208
/
reward.go
88 lines (74 loc) · 2.86 KB
/
reward.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package keeper
import (
"github.com/NibiruChain/collections"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/NibiruChain/nibiru/x/oracle/types"
)
func (k Keeper) AllocateRewards(ctx sdk.Context, funderModule string, totalCoins sdk.Coins, votePeriods uint64) error {
votePeriodCoins := make(sdk.Coins, len(totalCoins))
for i, coin := range totalCoins {
newCoin := sdk.NewCoin(coin.Denom, coin.Amount.QuoRaw(int64(votePeriods)))
votePeriodCoins[i] = newCoin
}
id := k.RewardsID.Next(ctx)
k.Rewards.Insert(ctx, id, types.Rewards{
Id: id,
VotePeriods: votePeriods,
Coins: votePeriodCoins,
})
return k.bankKeeper.SendCoinsFromModuleToModule(ctx, funderModule, types.ModuleName, totalCoins)
}
// rewardWinners gives out a portion of spread fees collected in the
// oracle reward pool to the oracle voters that voted faithfully.
func (k Keeper) rewardWinners(
ctx sdk.Context,
validatorPerformances types.ValidatorPerformances,
) {
totalRewardWeight := validatorPerformances.TotalRewardWeight()
if totalRewardWeight == 0 {
return
}
var totalRewards sdk.DecCoins
rewards := k.GatherRewardsForVotePeriod(ctx)
totalRewards = totalRewards.Add(sdk.NewDecCoinsFromCoins(rewards...)...)
var distributedRewards sdk.Coins
for _, validatorPerformance := range validatorPerformances {
validator := k.StakingKeeper.Validator(ctx, validatorPerformance.ValAddress)
if validator == nil {
continue
}
rewardPortion, _ := totalRewards.MulDec(sdk.NewDec(validatorPerformance.RewardWeight).QuoInt64(totalRewardWeight)).TruncateDecimal()
k.distrKeeper.AllocateTokensToValidator(ctx, validator, sdk.NewDecCoinsFromCoins(rewardPortion...))
distributedRewards = distributedRewards.Add(rewardPortion...)
}
// Move distributed reward to distribution module
err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, k.distrModuleName, distributedRewards)
if err != nil {
k.Logger(ctx).Error("Failed to send coins to distribution module", "err", err)
}
}
// GatherRewardsForVotePeriod retrieves the pair rewards for the provided pair and current vote period.
func (k Keeper) GatherRewardsForVotePeriod(ctx sdk.Context) sdk.Coins {
coins := sdk.NewCoins()
// iterate over
for _, rewardId := range k.Rewards.Iterate(ctx, collections.Range[uint64]{}).Keys() {
pairReward, err := k.Rewards.Get(ctx, rewardId)
if err != nil {
k.Logger(ctx).Error("Failed to get reward", "err", err)
continue
}
coins = coins.Add(pairReward.Coins...)
// Decrease the remaining vote periods of the PairReward.
pairReward.VotePeriods -= 1
if pairReward.VotePeriods == 0 {
// If the distribution period count drops to 0: the reward instance is removed.
err := k.Rewards.Delete(ctx, rewardId)
if err != nil {
k.Logger(ctx).Error("Failed to delete pair reward", "err", err)
}
} else {
k.Rewards.Insert(ctx, rewardId, pairReward)
}
}
return coins
}