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

fix: reward calculation for different types of token #316

Merged
merged 1 commit into from
Feb 28, 2024
Merged
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
1 change: 1 addition & 0 deletions proto/alliance/alliance/params.proto
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ message RewardHistory {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
string alliance = 3;
}
12 changes: 0 additions & 12 deletions x/alliance/keeper/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ func (k Keeper) InitializeAllianceAssets(ctx sdk.Context, assets []*types.Allian
continue
}
asset.IsInitialized = true
k.IterateAllianceValidatorInfo(ctx, func(valAddr sdk.ValAddress, info types.AllianceValidatorInfo) bool {
k.CreateInitialRewardWeightChangeSnapshot(ctx, asset.Denom, valAddr, info)
return false
})
k.SetAsset(ctx, *asset)
}
}
Expand Down Expand Up @@ -343,14 +339,6 @@ func (k Keeper) SetRewardWeightChangeSnapshot(ctx sdk.Context, asset types.Allia
k.setRewardWeightChangeSnapshot(ctx, asset.Denom, val.GetOperator(), uint64(ctx.BlockHeight()), snapshot)
}

func (k Keeper) CreateInitialRewardWeightChangeSnapshot(ctx sdk.Context, denom string, valAddr sdk.ValAddress, info types.AllianceValidatorInfo) {
snapshot := types.RewardWeightChangeSnapshot{
PrevRewardWeight: sdk.ZeroDec(),
RewardHistories: info.GlobalRewardHistory,
}
k.setRewardWeightChangeSnapshot(ctx, denom, valAddr, uint64(ctx.BlockHeight()), snapshot)
}

func (k Keeper) setRewardWeightChangeSnapshot(ctx sdk.Context, denom string, valAddr sdk.ValAddress, height uint64, snapshot types.RewardWeightChangeSnapshot) {
key := types.GetRewardWeightChangeSnapshotKey(denom, valAddr, height)
store := ctx.KVStore(k.storeKey)
Expand Down
70 changes: 39 additions & 31 deletions x/alliance/keeper/reward.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ func (k Keeper) ClaimDelegationRewards(
// It takes past reward_rate changes into account by using the RewardRateChangeSnapshot entry
func (k Keeper) CalculateDelegationRewards(ctx sdk.Context, delegation types.Delegation, val types.AllianceValidator, asset types.AllianceAsset) (sdk.Coins, types.RewardHistories, error) {
totalRewards := sdk.NewCoins()
currentRewardHistory := types.NewRewardHistories(val.GlobalRewardHistory)
delegationRewardHistories := types.NewRewardHistories(delegation.RewardHistory)
currentRewardHistory := types.NewRewardHistories(val.GlobalRewardHistory).GetIndexByAlliance(asset.Denom)
delegationRewardHistories := types.NewRewardHistories(delegation.RewardHistory).GetIndexByAlliance(asset.Denom)
// If there are reward rate changes between last and current claim, sequentially claim with the help of the snapshots
snapshotIter := k.IterateWeightChangeSnapshot(ctx, asset.Denom, val.GetOperator(), delegation.LastRewardClaimHeight)
for ; snapshotIter.Valid(); snapshotIter.Next() {
Expand All @@ -113,15 +113,22 @@ func accumulateRewards(latestRewardHistories types.RewardHistories, rewardHistor

delegationTokens := sdk.NewDecFromInt(types.GetDelegationTokens(delegation, validator, asset).Amount)
for _, history := range latestRewardHistories {
rewardHistory, found := rewardHistories.GetIndexByDenom(history.Denom)
rewardHistory, found := rewardHistories.GetIndexByDenom(history.Denom, history.Alliance)
if !found {
rewardHistory.Denom = history.Denom
rewardHistory.Alliance = history.Alliance
rewardHistory.Index = sdk.ZeroDec()
}
if rewardHistory.Index.GTE(history.Index) {
continue
}
claimWeight := delegationTokens.Mul(rewardWeight)
var claimWeight sdk.Dec
// Handle legacy reward history that does not have a specific alliance
if rewardHistory.Alliance == "" {
claimWeight = delegationTokens.Mul(rewardWeight)
} else {
claimWeight = delegationTokens
}
totalClaimable := (history.Index.Sub(rewardHistory.Index)).Mul(claimWeight)
rewardHistory.Index = history.Index
rewards = rewards.Add(sdk.NewCoin(history.Denom, totalClaimable.TruncateInt()))
Expand All @@ -140,22 +147,35 @@ func (k Keeper) AddAssetsToRewardPool(ctx sdk.Context, from sdk.AccAddress, val
if len(val.TotalDelegatorShares) == 0 {
return nil
}
alliances := k.GetAllAssets(ctx)

totalAssetWeight := k.totalAssetWeight(ctx, val)
if totalAssetWeight.IsZero() {
// Do nothing since there are no assets to distribute rewards to
return nil
// Get total reward weight to normalize weights
totalRewardWeight := sdk.NewDec(0)
for _, asset := range alliances {
if shouldSkipRewardsToAsset(ctx, *asset, val) {
continue
}
totalRewardWeight = totalRewardWeight.Add(asset.RewardWeight)
}

for _, c := range coins {
rewardHistory, found := rewardHistories.GetIndexByDenom(c.Denom)
if !found {
rewardHistories = append(rewardHistories, types.RewardHistory{
Denom: c.Denom,
Index: sdk.NewDecFromInt(c.Amount).Quo(totalAssetWeight),
})
} else {
rewardHistory.Index = rewardHistory.Index.Add(sdk.NewDecFromInt(c.Amount).Quo(totalAssetWeight))
for _, asset := range alliances {
if shouldSkipRewardsToAsset(ctx, *asset, val) {
continue
}
normalizedWeight := asset.RewardWeight.Quo(totalRewardWeight)
for _, c := range coins {
rewardHistory, found := rewardHistories.GetIndexByDenom(c.Denom, asset.Denom)
totalTokens := val.TotalTokensWithAsset(*asset)
difference := sdk.NewDecFromInt(c.Amount).Mul(normalizedWeight).Quo(totalTokens)
if !found {
rewardHistories = append(rewardHistories, types.RewardHistory{
Denom: c.Denom,
Alliance: asset.Denom,
Index: difference,
})
} else {
rewardHistory.Index = rewardHistory.Index.Add(difference)
}
}
}

Expand All @@ -169,18 +189,6 @@ func (k Keeper) AddAssetsToRewardPool(ctx sdk.Context, from sdk.AccAddress, val
return nil
}

func (k Keeper) totalAssetWeight(ctx sdk.Context, val types.AllianceValidator) sdk.Dec {
total := sdk.ZeroDec()
for _, token := range val.TotalDelegatorShares {
asset, found := k.GetAssetByDenom(ctx, token.Denom)
if !found {
continue
}
if !asset.RewardsStarted(ctx.BlockTime()) {
continue
}
totalValTokens := val.TotalTokensWithAsset(asset)
total = total.Add(asset.RewardWeight.Mul(totalValTokens))
}
return total
func shouldSkipRewardsToAsset(ctx sdk.Context, asset types.AllianceAsset, val types.AllianceValidator) bool {
return asset.TotalTokens.IsZero() || !asset.RewardsStarted(ctx.BlockTime()) || val.TotalTokensWithAsset(asset).IsZero()
}
2 changes: 1 addition & 1 deletion x/alliance/keeper/tests/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ func TestClaimQueryReward(t *testing.T) {
Rewards: []sdk.Coin{
{
Denom: ULunaAlliance,
Amount: math.NewInt(32666),
Amount: math.NewInt(32665),
},
},
}, queryDelegation)
Expand Down
Loading
Loading