From 3fc2a63556e110221a6dfd5f012fc046fbd6d1d5 Mon Sep 17 00:00:00 2001 From: Denali Marsh Date: Wed, 7 Jul 2021 18:50:14 +0200 Subject: [PATCH] Refactor to DelegatorClaim and implement new MsgClaimDelegatorReward (#948) * update claim attribute type to MultiRewardIndexes * update param attribute type to MultiRewardPeriods * keeper: update params to match types * keeper: update delegator core keeper methods * keeper: update InitializeHardDelegatorReward * keeper: update SynchronizeHardDelegatorRewards * remove reward factor in favor of reward indexes * update querier * fix test: delegator init test * fix test: delegator sync test * implement delegator reward accumulation * fix test: delegator general tests * add legact types, update v0_11 -> v0_14 migration * remove duplicate import form v0_15 migration * implement v0_15incentive migration * test data and migration test * add multiple reward denoms to init/sync tests * update delegator test with multiple reward coins * clean up simulation sync * types: introduce DelegatorClaim, refactor HardClaim * add core DelegateClaim store methods * refactor delegator reward init, accumulation, sync * update hooks * update params and genesis logic * update abci * update types tests * update querier types/keeper for compile * update supply rewards tests * update borrow reward tests * update delegator reward tests * update handler/genesis test for compile * add new msg type * implement delegator claim payouts * submission + handling of new msg * implement new querier types/keeper logic * add new queries to cli/rest * update migration * register new msgs/types on codec * remove delegator syncing from hard sync method --- migrate/v0_15/migrate.go | 14 +- migrate/v0_15/migrate_test.go | 2 + x/incentive/abci.go | 4 +- x/incentive/alias.go | 83 +++++------ x/incentive/client/cli/query.go | 80 ++++++++++- x/incentive/client/cli/tx.go | 67 +++++++++ x/incentive/client/rest/query.go | 88 +++++++++++- x/incentive/client/rest/tx.go | 69 ++++++++- x/incentive/genesis.go | 51 ++++--- x/incentive/genesis_test.go | 1 + x/incentive/handler.go | 26 ++++ x/incentive/handler_test.go | 5 +- x/incentive/keeper/hooks.go | 10 +- x/incentive/keeper/integration_test.go | 4 +- x/incentive/keeper/keeper.go | 79 +++++++++-- x/incentive/keeper/params.go | 6 +- x/incentive/keeper/payout.go | 125 ++++++++++++++++- x/incentive/keeper/querier.go | 92 +++++++++++- x/incentive/keeper/rewards_borrow.go | 4 +- .../keeper/rewards_borrow_init_test.go | 2 +- .../keeper/rewards_borrow_sync_test.go | 14 +- .../keeper/rewards_borrow_update_test.go | 8 +- x/incentive/keeper/rewards_delegator.go | 131 ++++++++++++++---- .../keeper/rewards_delegator_init_test.go | 44 +++--- .../keeper/rewards_delegator_sync_test.go | 97 +++++++------ x/incentive/keeper/rewards_delegator_test.go | 92 ++++++------ x/incentive/keeper/rewards_supply.go | 57 +------- .../keeper/rewards_supply_init_test.go | 2 +- .../keeper/rewards_supply_sync_test.go | 14 +- .../keeper/rewards_supply_update_test.go | 8 +- x/incentive/keeper/unit_test.go | 8 +- x/incentive/types/claims.go | 93 ++++++++++--- x/incentive/types/codec.go | 3 + x/incentive/types/genesis.go | 61 ++++---- x/incentive/types/genesis_test.go | 1 + x/incentive/types/keys.go | 25 ++-- x/incentive/types/msg.go | 89 +++++++++++- x/incentive/types/params.go | 41 +++--- x/incentive/types/params_test.go | 80 +++++------ x/incentive/types/querier.go | 56 ++++++-- 40 files changed, 1275 insertions(+), 461 deletions(-) diff --git a/migrate/v0_15/migrate.go b/migrate/v0_15/migrate.go index 8a0d5686..0933d333 100644 --- a/migrate/v0_15/migrate.go +++ b/migrate/v0_15/migrate.go @@ -297,8 +297,9 @@ func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisSt usdxMintingClaims = append(usdxMintingClaims, usdxMintingClaim) } - // Migrate Hard protocol claims (including delegation rewards) + // Migrate Hard protocol claims (includes creating new Delegator claims) var hardClaims v0_15incentive.HardLiquidityProviderClaims + var delegatorClaims v0_15incentive.DelegatorClaims for _, claim := range incentiveGS.HardLiquidityProviderClaims { // Migrate supply multi reward indexes var supplyMultiRewardIndexes v0_15incentive.MultiRewardIndexes @@ -324,7 +325,7 @@ func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisSt borrowMultiRewardIndexes = append(borrowMultiRewardIndexes, borrowMultiRewardIndex) } - // Migrate delegator reward indexes to multi reward indexes under BondDenom + // Migrate delegator reward indexes to multi reward indexes inside DelegatorClaims var delegatorMultiRewardIndexes v0_15incentive.MultiRewardIndexes var delegatorRewardIndexes v0_15incentive.RewardIndexes for _, ri := range claim.DelegatorRewardIndexes { @@ -334,8 +335,14 @@ func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisSt delegatorMultiRewardIndex := v0_15incentive.NewMultiRewardIndex(v0_15incentive.BondDenom, delegatorRewardIndexes) delegatorMultiRewardIndexes = append(delegatorMultiRewardIndexes, delegatorMultiRewardIndex) + // TODO: It's impossible to distinguish between rewards from delegation vs. liquidity providing + // as they're all combined inside claim.Reward, so I'm just putting them all inside + // the hard claim to avoid duplicating rewards. + delegatorClaim := v0_15incentive.NewDelegatorClaim(claim.Owner, sdk.NewCoins(), delegatorMultiRewardIndexes) + delegatorClaims = append(delegatorClaims, delegatorClaim) + hardClaim := v0_15incentive.NewHardLiquidityProviderClaim(claim.Owner, claim.Reward, - supplyMultiRewardIndexes, borrowMultiRewardIndexes, delegatorMultiRewardIndexes) + supplyMultiRewardIndexes, borrowMultiRewardIndexes) hardClaims = append(hardClaims, hardClaim) } @@ -348,5 +355,6 @@ func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisSt v0_15incentive.DefaultGenesisAccumulationTimes, // There is no previous swap rewards to accumulation starts at genesis time. usdxMintingClaims, hardClaims, + delegatorClaims, ) } diff --git a/migrate/v0_15/migrate_test.go b/migrate/v0_15/migrate_test.go index a05218b8..5632e7be 100644 --- a/migrate/v0_15/migrate_test.go +++ b/migrate/v0_15/migrate_test.go @@ -75,4 +75,6 @@ func TestIncentive(t *testing.T) { require.Equal(t, len(oldIncentiveGenState.USDXMintingClaims), len(newGenState.USDXMintingClaims)) require.Equal(t, len(oldIncentiveGenState.HardLiquidityProviderClaims), len(newGenState.HardLiquidityProviderClaims)) + // 1 new DelegatorClaim should have been created for each existing HardLiquidityProviderClaim + require.Equal(t, len(oldIncentiveGenState.HardLiquidityProviderClaims), len(newGenState.DelegatorClaims)) } diff --git a/x/incentive/abci.go b/x/incentive/abci.go index 2ce8a17b..00a814d1 100644 --- a/x/incentive/abci.go +++ b/x/incentive/abci.go @@ -27,8 +27,8 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { panic(err) } } - for _, rp := range params.HardDelegatorRewardPeriods { - err := k.AccumulateHardDelegatorRewards(ctx, rp) + for _, rp := range params.DelegatorRewardPeriods { + err := k.AccumulateDelegatorRewards(ctx, rp) if err != nil { panic(err) } diff --git a/x/incentive/alias.go b/x/incentive/alias.go index 7008aa93..e02db75b 100644 --- a/x/incentive/alias.go +++ b/x/incentive/alias.go @@ -84,47 +84,48 @@ var ( CalculateTimeElapsed = keeper.CalculateTimeElapsed // variable aliases - ModuleCdc = types.ModuleCdc - ErrClaimNotFound = types.ErrClaimNotFound - ErrRewardPeriodNotFound = types.ErrRewardPeriodNotFound - ErrInvalidAccountType = types.ErrInvalidAccountType - ErrNoClaimsFound = types.ErrNoClaimsFound - ErrInsufficientModAccountBalance = types.ErrInsufficientModAccountBalance - ErrAccountNotFound = types.ErrAccountNotFound - ErrInvalidMultiplier = types.ErrInvalidMultiplier - ErrZeroClaim = types.ErrZeroClaim - ErrClaimExpired = types.ErrClaimExpired - ErrInvalidClaimType = types.ErrInvalidClaimType - ErrInvalidClaimOwner = types.ErrInvalidClaimOwner - USDXMintingClaimKeyPrefix = types.USDXMintingClaimKeyPrefix - USDXMintingRewardFactorKeyPrefix = types.USDXMintingRewardFactorKeyPrefix - PreviousUSDXMintingRewardAccrualTimeKeyPrefix = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix - HardLiquidityClaimKeyPrefix = types.HardLiquidityClaimKeyPrefix - HardSupplyRewardIndexesKeyPrefix = types.HardSupplyRewardIndexesKeyPrefix - PreviousHardSupplyRewardAccrualTimeKeyPrefix = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix - HardBorrowRewardIndexesKeyPrefix = types.HardBorrowRewardIndexesKeyPrefix - PreviousHardBorrowRewardAccrualTimeKeyPrefix = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix - HardDelegatorRewardIndexesKeyPrefix = types.HardDelegatorRewardIndexesKeyPrefix - PreviousHardDelegatorRewardAccrualTimeKeyPrefix = types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix - USDXMintingRewardDenom = types.USDXMintingRewardDenom - HardLiquidityRewardDenom = types.HardLiquidityRewardDenom - KeyUSDXMintingRewardPeriods = types.KeyUSDXMintingRewardPeriods - KeyHardSupplyRewardPeriods = types.KeyHardSupplyRewardPeriods - KeyHardBorrowRewardPeriods = types.KeyHardBorrowRewardPeriods - KeyHardDelegatorRewardPeriods = types.KeyHardDelegatorRewardPeriods - KeyClaimEnd = types.KeyClaimEnd - KeyMultipliers = types.KeyMultipliers - DefaultActive = types.DefaultActive - DefaultRewardPeriods = types.DefaultRewardPeriods - DefaultMultiRewardPeriods = types.DefaultMultiRewardPeriods - DefaultMultipliers = types.DefaultMultipliers - DefaultUSDXClaims = types.DefaultUSDXClaims - DefaultHardClaims = types.DefaultHardClaims - DefaultGenesisAccumulationTimes = types.DefaultGenesisAccumulationTimes - DefaultClaimEnd = types.DefaultClaimEnd - GovDenom = types.GovDenom - PrincipalDenom = types.PrincipalDenom - IncentiveMacc = types.IncentiveMacc + ModuleCdc = types.ModuleCdc + ErrClaimNotFound = types.ErrClaimNotFound + ErrRewardPeriodNotFound = types.ErrRewardPeriodNotFound + ErrInvalidAccountType = types.ErrInvalidAccountType + ErrNoClaimsFound = types.ErrNoClaimsFound + ErrInsufficientModAccountBalance = types.ErrInsufficientModAccountBalance + ErrAccountNotFound = types.ErrAccountNotFound + ErrInvalidMultiplier = types.ErrInvalidMultiplier + ErrZeroClaim = types.ErrZeroClaim + ErrClaimExpired = types.ErrClaimExpired + ErrInvalidClaimType = types.ErrInvalidClaimType + ErrInvalidClaimOwner = types.ErrInvalidClaimOwner + USDXMintingClaimKeyPrefix = types.USDXMintingClaimKeyPrefix + USDXMintingRewardFactorKeyPrefix = types.USDXMintingRewardFactorKeyPrefix + PreviousUSDXMintingRewardAccrualTimeKeyPrefix = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix + HardLiquidityClaimKeyPrefix = types.HardLiquidityClaimKeyPrefix + HardSupplyRewardIndexesKeyPrefix = types.HardSupplyRewardIndexesKeyPrefix + PreviousHardSupplyRewardAccrualTimeKeyPrefix = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix + HardBorrowRewardIndexesKeyPrefix = types.HardBorrowRewardIndexesKeyPrefix + PreviousHardBorrowRewardAccrualTimeKeyPrefix = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix + DelegatorRewardIndexesKeyPrefix = types.DelegatorRewardIndexesKeyPrefix + PreviousDelegatorRewardAccrualTimeKeyPrefix = types.PreviousDelegatorRewardAccrualTimeKeyPrefix + USDXMintingRewardDenom = types.USDXMintingRewardDenom + HardLiquidityRewardDenom = types.HardLiquidityRewardDenom + KeyUSDXMintingRewardPeriods = types.KeyUSDXMintingRewardPeriods + KeyHardSupplyRewardPeriods = types.KeyHardSupplyRewardPeriods + KeyHardBorrowRewardPeriods = types.KeyHardBorrowRewardPeriods + KeyDelegatorRewardPeriods = types.KeyDelegatorRewardPeriods + KeyClaimEnd = types.KeyClaimEnd + KeyMultipliers = types.KeyMultipliers + DefaultActive = types.DefaultActive + DefaultRewardPeriods = types.DefaultRewardPeriods + DefaultMultiRewardPeriods = types.DefaultMultiRewardPeriods + DefaultMultipliers = types.DefaultMultipliers + DefaultDelegatorClaims = types.DefaultDelegatorClaims + DefaultUSDXClaims = types.DefaultUSDXClaims + DefaultHardClaims = types.DefaultHardClaims + DefaultGenesisAccumulationTimes = types.DefaultGenesisAccumulationTimes + DefaultClaimEnd = types.DefaultClaimEnd + GovDenom = types.GovDenom + PrincipalDenom = types.PrincipalDenom + IncentiveMacc = types.IncentiveMacc ) type ( diff --git a/x/incentive/client/cli/query.go b/x/incentive/client/cli/query.go index 5f576b21..0c9e43f1 100644 --- a/x/incentive/client/cli/query.go +++ b/x/incentive/client/cli/query.go @@ -51,12 +51,14 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { $ %s query %s rewards --owner kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw $ %s query %s rewards --type hard $ %s query %s rewards --type usdx-minting + $ %s query %s rewards --type delegator $ %s query %s rewards --type hard --owner kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw $ %s query %s rewards --type hard --unsynced true `, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, - version.ClientName, types.ModuleName, version.ClientName, types.ModuleName)), + version.ClientName, types.ModuleName, version.ClientName, types.ModuleName, + version.ClientName, types.ModuleName)), Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { cliCtx := context.NewCLIContext().WithCodec(cdc) @@ -106,9 +108,26 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { } } return cliCtx.PrintOutput(claims) + case "delegator": + var claims types.DelegatorClaims + if boolUnsynced { + params := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner) + claims, err = executeDelegatorRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, params) + if err != nil { + return err + } + } else { + params := types.NewQueryDelegatorRewardsParams(page, limit, owner) + claims, err = executeDelegatorRewardsQuery(queryRoute, cdc, cliCtx, params) + if err != nil { + return err + } + } + return cliCtx.PrintOutput(claims) default: var hardClaims types.HardLiquidityProviderClaims var usdxMintingClaims types.USDXMintingClaims + var delegatorClaims types.DelegatorClaims if boolUnsynced { paramsHard := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner) hardClaims, err = executeHardRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, paramsHard) @@ -120,6 +139,11 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } + paramsDelegator := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner) + delegatorClaims, err = executeDelegatorRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, paramsDelegator) + if err != nil { + return err + } } else { paramsHard := types.NewQueryHardRewardsParams(page, limit, owner) hardClaims, err = executeHardRewardsQuery(queryRoute, cdc, cliCtx, paramsHard) @@ -131,6 +155,11 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { if err != nil { return err } + paramsDelegator := types.NewQueryDelegatorRewardsParams(page, limit, owner) + delegatorClaims, err = executeDelegatorRewardsQuery(queryRoute, cdc, cliCtx, paramsDelegator) + if err != nil { + return err + } } if len(hardClaims) > 0 { cliCtx.PrintOutput(hardClaims) @@ -138,6 +167,9 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command { if len(usdxMintingClaims) > 0 { cliCtx.PrintOutput(usdxMintingClaims) } + if len(delegatorClaims) > 0 { + cliCtx.PrintOutput(delegatorClaims) + } } return nil }, @@ -311,3 +343,49 @@ func executeUSDXMintingRewardsUnsyncedQuery(queryRoute string, cdc *codec.Codec, return claims, nil } + +func executeDelegatorRewardsQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, + params types.QueryDelegatorRewardsParams) (types.DelegatorClaims, error) { + bz, err := cdc.MarshalJSON(params) + if err != nil { + return types.DelegatorClaims{}, err + } + + route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetDelegatorRewards) + res, height, err := cliCtx.QueryWithData(route, bz) + if err != nil { + return types.DelegatorClaims{}, err + } + + cliCtx = cliCtx.WithHeight(height) + + var claims types.DelegatorClaims + if err := cdc.UnmarshalJSON(res, &claims); err != nil { + return types.DelegatorClaims{}, fmt.Errorf("failed to unmarshal claims: %w", err) + } + + return claims, nil +} + +func executeDelegatorRewardsUnsyncedQuery(queryRoute string, cdc *codec.Codec, cliCtx context.CLIContext, + params types.QueryDelegatorRewardsUnsyncedParams) (types.DelegatorClaims, error) { + bz, err := cdc.MarshalJSON(params) + if err != nil { + return types.DelegatorClaims{}, err + } + + route := fmt.Sprintf("custom/%s/%s", queryRoute, types.QueryGetDelegatorRewardsUnsynced) + res, height, err := cliCtx.QueryWithData(route, bz) + if err != nil { + return types.DelegatorClaims{}, err + } + + cliCtx = cliCtx.WithHeight(height) + + var claims types.DelegatorClaims + if err := cdc.UnmarshalJSON(res, &claims); err != nil { + return types.DelegatorClaims{}, fmt.Errorf("failed to unmarshal claims: %w", err) + } + + return claims, nil +} diff --git a/x/incentive/client/cli/tx.go b/x/incentive/client/cli/tx.go index 59f66292..9c414097 100644 --- a/x/incentive/client/cli/tx.go +++ b/x/incentive/client/cli/tx.go @@ -30,6 +30,8 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { getCmdClaimCdpVVesting(cdc), getCmdClaimHard(cdc), getCmdClaimHardVVesting(cdc), + getCmdClaimDelegator(cdc), + getCmdClaimDelegatorVVesting(cdc), )...) return incentiveTxCmd @@ -164,3 +166,68 @@ func getCmdClaimHard(cdc *codec.Codec) *cobra.Command { }, } } + +func getCmdClaimDelegator(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "claim-delegator [multiplier]", + Short: "claim sender's delegator rewards using a given multiplier", + Long: strings.TrimSpace( + fmt.Sprintf(`Claim sender's outstanding delegator rewards using given multiplier + + Example: + $ %s tx %s claim-delegator large + `, version.ClientName, types.ModuleName), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + inBuf := bufio.NewReader(cmd.InOrStdin()) + cliCtx := context.NewCLIContext().WithCodec(cdc) + txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) + + sender := cliCtx.GetFromAddress() + multiplier := args[0] + + msg := types.NewMsgClaimDelegatorReward(sender, multiplier) + err := msg.ValidateBasic() + if err != nil { + return err + } + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) + }, + } +} + +func getCmdClaimDelegatorVVesting(cdc *codec.Codec) *cobra.Command { + return &cobra.Command{ + Use: "claim-delegator-vesting [multiplier] [receiver]", + Short: "claim delegator rewards on behalf of a validator vesting account using a given multiplier", + Long: strings.TrimSpace( + fmt.Sprintf(`Claim sender's outstanding delegator rewards on behalf of a validator vesting account using given multiplier + + Example: + $ %s tx %s claim-delegator-vesting large kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw + `, version.ClientName, types.ModuleName), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + inBuf := bufio.NewReader(cmd.InOrStdin()) + cliCtx := context.NewCLIContext().WithCodec(cdc) + txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) + + sender := cliCtx.GetFromAddress() + multiplier := args[0] + receiverStr := args[1] + receiver, err := sdk.AccAddressFromBech32(receiverStr) + if err != nil { + return err + } + + msg := types.NewMsgClaimDelegatorRewardVVesting(sender, receiver, multiplier) + err = msg.ValidateBasic() + if err != nil { + return err + } + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) + }, + } +} diff --git a/x/incentive/client/rest/query.go b/x/incentive/client/rest/query.go index b9098f42..1701392b 100644 --- a/x/incentive/client/rest/query.go +++ b/x/incentive/client/rest/query.go @@ -66,10 +66,14 @@ func queryRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { case "usdx_minting": params := types.NewQueryUSDXMintingRewardsUnsyncedParams(page, limit, owner) executeUSDXMintingRewardsUnsyncedQuery(w, cliCtx, params) + case "delegator": + params := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner) + executeDelegatorRewardsUnsyncedQuery(w, cliCtx, params) default: hardParams := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner) usdxMintingParams := types.NewQueryUSDXMintingRewardsUnsyncedParams(page, limit, owner) - executeBothUnsyncedRewardQueries(w, cliCtx, hardParams, usdxMintingParams) + delegatorParams := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner) + executeAllUnsyncedRewardQueries(w, cliCtx, hardParams, usdxMintingParams, delegatorParams) } } else { switch strings.ToLower(rewardType) { @@ -79,10 +83,14 @@ func queryRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { case "usdx_minting": params := types.NewQueryUSDXMintingRewardsParams(page, limit, owner) executeUSDXMintingRewardsQuery(w, cliCtx, params) + case "delegator": + params := types.NewQueryDelegatorRewardsParams(page, limit, owner) + executeDelegatorRewardsQuery(w, cliCtx, params) default: hardParams := types.NewQueryHardRewardsParams(page, limit, owner) usdxMintingParams := types.NewQueryUSDXMintingRewardsParams(page, limit, owner) - executeBothRewardQueries(w, cliCtx, hardParams, usdxMintingParams) + delegatorParams := types.NewQueryDelegatorRewardsParams(page, limit, owner) + executeAllRewardQueries(w, cliCtx, hardParams, usdxMintingParams, delegatorParams) } } } @@ -214,8 +222,43 @@ func executeUSDXMintingRewardsUnsyncedQuery(w http.ResponseWriter, cliCtx contex rest.PostProcessResponse(w, cliCtx, res) } -func executeBothRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, - hardParams types.QueryHardRewardsParams, usdxMintingParams types.QueryUSDXMintingRewardsParams) { +func executeDelegatorRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryDelegatorRewardsParams) { + bz, err := cliCtx.Codec.MarshalJSON(params) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetDelegatorRewards), bz) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) +} + +func executeDelegatorRewardsUnsyncedQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryDelegatorRewardsUnsyncedParams) { + bz, err := cliCtx.Codec.MarshalJSON(params) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) + return + } + + res, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetDelegatorRewardsUnsynced), bz) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + cliCtx = cliCtx.WithHeight(height) + rest.PostProcessResponse(w, cliCtx, res) +} + +func executeAllRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, + hardParams types.QueryHardRewardsParams, usdxMintingParams types.QueryUSDXMintingRewardsParams, + delegatorParams types.QueryDelegatorRewardsParams) { hardBz, err := cliCtx.Codec.MarshalJSON(hardParams) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) @@ -244,16 +287,32 @@ func executeBothRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, var usdxMintingClaims types.USDXMintingClaims cliCtx.Codec.MustUnmarshalJSON(usdxMintingRes, &usdxMintingClaims) + delegatorBz, err := cliCtx.Codec.MarshalJSON(delegatorParams) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) + return + } + + delegatorRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetDelegatorRewards), delegatorBz) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + var delegatorClaims types.DelegatorClaims + cliCtx.Codec.MustUnmarshalJSON(delegatorRes, &delegatorClaims) + cliCtx = cliCtx.WithHeight(height) type rewardResult struct { HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"` UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` + DelegatorClaims types.DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"` } res := rewardResult{ HardClaims: hardClaims, UsdxMintingClaims: usdxMintingClaims, + DelegatorClaims: delegatorClaims, } resBz, err := cliCtx.Codec.MarshalJSON(res) @@ -265,8 +324,9 @@ func executeBothRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, rest.PostProcessResponse(w, cliCtx, resBz) } -func executeBothUnsyncedRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, - hardParams types.QueryHardRewardsUnsyncedParams, usdxMintingParams types.QueryUSDXMintingRewardsUnsyncedParams) { +func executeAllUnsyncedRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, + hardParams types.QueryHardRewardsUnsyncedParams, usdxMintingParams types.QueryUSDXMintingRewardsUnsyncedParams, + delegatorParams types.QueryDelegatorRewardsUnsyncedParams) { hardBz, err := cliCtx.Codec.MarshalJSON(hardParams) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) @@ -295,16 +355,32 @@ func executeBothUnsyncedRewardQueries(w http.ResponseWriter, cliCtx context.CLIC var usdxMintingClaims types.USDXMintingClaims cliCtx.Codec.MustUnmarshalJSON(usdxMintingRes, &usdxMintingClaims) + delegatorBz, err := cliCtx.Codec.MarshalJSON(delegatorParams) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) + return + } + + delegatorRes, height, err := cliCtx.QueryWithData(fmt.Sprintf("custom/incentive/%s", types.QueryGetDelegatorRewardsUnsynced), delegatorBz) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + var delegatorClaims types.DelegatorClaims + cliCtx.Codec.MustUnmarshalJSON(delegatorRes, &delegatorClaims) + cliCtx = cliCtx.WithHeight(height) type rewardResult struct { HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"` UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` + DelegatorClaims types.DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"` } res := rewardResult{ HardClaims: hardClaims, UsdxMintingClaims: usdxMintingClaims, + DelegatorClaims: delegatorClaims, } resBz, err := cliCtx.Codec.MarshalJSON(res) diff --git a/x/incentive/client/rest/tx.go b/x/incentive/client/rest/tx.go index c3396670..884b1c18 100644 --- a/x/incentive/client/rest/tx.go +++ b/x/incentive/client/rest/tx.go @@ -20,7 +20,8 @@ func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { r.HandleFunc("/incentive/claim-cdp-vesting", postClaimCdpVVestingHandlerFn(cliCtx)).Methods("POST") r.HandleFunc("/incentive/claim-hard", postClaimHardHandlerFn(cliCtx)).Methods("POST") r.HandleFunc("/incentive/claim-hard-vesting", postClaimHardVVestingHandlerFn(cliCtx)).Methods("POST") - + r.HandleFunc("/incentive/claim-delegator", postClaimDelegatorHandlerFn(cliCtx)).Methods("POST") + r.HandleFunc("/incentive/claim-delegator-vesting", postClaimDelegatorVVestingHandlerFn(cliCtx)).Methods("POST") } func postClaimCdpHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { @@ -154,3 +155,69 @@ func postClaimHardVVestingHandlerFn(cliCtx context.CLIContext) http.HandlerFunc utils.WriteGenerateStdTxResponse(w, cliCtx, requestBody.BaseReq, []sdk.Msg{msg}) } } + +func postClaimDelegatorHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var requestBody PostClaimReq + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &requestBody) { + return + } + + requestBody.BaseReq = requestBody.BaseReq.Sanitize() + if !requestBody.BaseReq.ValidateBasic(w) { + return + } + + fromAddr, err := sdk.AccAddressFromBech32(requestBody.BaseReq.From) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + if !bytes.Equal(fromAddr, requestBody.Sender) { + rest.WriteErrorResponse(w, http.StatusUnauthorized, fmt.Sprintf("expected: %s, got: %s", fromAddr, requestBody.Sender)) + return + } + + msg := types.NewMsgClaimDelegatorReward(requestBody.Sender, requestBody.MultiplierName) + if err := msg.ValidateBasic(); err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + utils.WriteGenerateStdTxResponse(w, cliCtx, requestBody.BaseReq, []sdk.Msg{msg}) + } +} + +func postClaimDelegatorVVestingHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var requestBody PostClaimVVestingReq + if !rest.ReadRESTReq(w, r, cliCtx.Codec, &requestBody) { + return + } + + requestBody.BaseReq = requestBody.BaseReq.Sanitize() + if !requestBody.BaseReq.ValidateBasic(w) { + return + } + + fromAddr, err := sdk.AccAddressFromBech32(requestBody.BaseReq.From) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + if !bytes.Equal(fromAddr, requestBody.Sender) { + rest.WriteErrorResponse(w, http.StatusUnauthorized, fmt.Sprintf("expected: %s, got: %s", fromAddr, requestBody.Sender)) + return + } + + msg := types.NewMsgClaimDelegatorRewardVVesting(requestBody.Sender, requestBody.Receiver, requestBody.MultiplierName) + if err := msg.ValidateBasic(); err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + utils.WriteGenerateStdTxResponse(w, cliCtx, requestBody.BaseReq, []sdk.Msg{msg}) + } +} diff --git a/x/incentive/genesis.go b/x/incentive/genesis.go index 67086c96..08b8abf7 100644 --- a/x/incentive/genesis.go +++ b/x/incentive/genesis.go @@ -48,13 +48,13 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep k.SetHardBorrowRewardIndexes(ctx, mrp.CollateralType, newRewardIndexes) } - for _, drp := range gs.Params.HardDelegatorRewardPeriods { + for _, drp := range gs.Params.DelegatorRewardPeriods { newRewardIndexes := types.RewardIndexes{} for _, rc := range drp.RewardsPerSecond { ri := types.NewRewardIndex(rc.Denom, sdk.ZeroDec()) newRewardIndexes = append(newRewardIndexes, ri) } - k.SetHardDelegatorRewardIndexes(ctx, drp.CollateralType, newRewardIndexes) + k.SetDelegatorRewardIndexes(ctx, drp.CollateralType, newRewardIndexes) } k.SetParams(ctx, gs.Params) @@ -71,8 +71,8 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep k.SetPreviousHardBorrowRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) } - for _, gat := range gs.HardDelegatorAccumulationTimes { - k.SetPreviousHardDelegatorRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) + for _, gat := range gs.DelegatorAccumulationTimes { + k.SetPreviousDelegatorRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) } for _, gat := range gs.SwapAccumulationTimes { k.SetSwapRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) @@ -102,14 +102,18 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep } } } - for j, dri := range claim.DelegatorRewardIndexes { - for k, ri := range dri.RewardIndexes { + k.SetHardLiquidityProviderClaim(ctx, claim) + } + + for i, claim := range gs.DelegatorClaims { + for j, mri := range claim.RewardIndexes { + for k, ri := range mri.RewardIndexes { if ri.RewardFactor != sdk.ZeroDec() { - gs.HardLiquidityProviderClaims[i].DelegatorRewardIndexes[j].RewardIndexes[k].RewardFactor = sdk.ZeroDec() + gs.DelegatorClaims[i].RewardIndexes[j].RewardIndexes[k].RewardFactor = sdk.ZeroDec() } } } - k.SetHardLiquidityProviderClaim(ctx, claim) + k.SetDelegatorClaim(ctx, claim) } } @@ -119,9 +123,11 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { usdxClaims := k.GetAllUSDXMintingClaims(ctx) hardClaims := k.GetAllHardLiquidityProviderClaims(ctx) + delegatorClaims := k.GetAllDelegatorClaims(ctx) synchronizedUsdxClaims := types.USDXMintingClaims{} synchronizedHardClaims := types.HardLiquidityProviderClaims{} + synchronizedDelegatorClaims := types.DelegatorClaims{} for _, usdxClaim := range usdxClaims { claim, err := k.SynchronizeUSDXMintingClaim(ctx, usdxClaim) @@ -150,12 +156,20 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { claim.SupplyRewardIndexes[i].RewardIndexes[j].RewardFactor = sdk.ZeroDec() } } - for i, dri := range claim.DelegatorRewardIndexes { - for j := range dri.RewardIndexes { - claim.DelegatorRewardIndexes[i].RewardIndexes[j].RewardFactor = sdk.ZeroDec() + synchronizedHardClaims = append(synchronizedHardClaims, claim) + } + + for _, delegatorClaim := range delegatorClaims { + claim, err := k.SynchronizeDelegatorClaim(ctx, delegatorClaim) + if err != nil { + panic(err) + } + for i, ri := range claim.RewardIndexes { + for j := range ri.RewardIndexes { + claim.RewardIndexes[i].RewardIndexes[j].RewardFactor = sdk.ZeroDec() } } - synchronizedHardClaims = append(synchronizedHardClaims, claim) + synchronizedDelegatorClaims = append(synchronizedDelegatorClaims, delegatorClaim) } var usdxMintingGats GenesisAccumulationTimes @@ -188,14 +202,14 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { hardBorrowGats = append(hardBorrowGats, gat) } - var hardDelegatorGats GenesisAccumulationTimes - for _, rp := range params.HardDelegatorRewardPeriods { - pat, found := k.GetPreviousHardDelegatorRewardAccrualTime(ctx, rp.CollateralType) + var delegatorGats GenesisAccumulationTimes + for _, rp := range params.DelegatorRewardPeriods { + pat, found := k.GetPreviousDelegatorRewardAccrualTime(ctx, rp.CollateralType) if !found { - panic(fmt.Sprintf("expected previous hard delegator reward accrual time to be set in state for %s", rp.CollateralType)) + panic(fmt.Sprintf("expected previous delegator reward accrual time to be set in state for %s", rp.CollateralType)) } gat := types.NewGenesisAccumulationTime(rp.CollateralType, pat) - hardDelegatorGats = append(hardDelegatorGats, gat) + delegatorGats = append(delegatorGats, gat) } var swapGats GenesisAccumulationTimes @@ -209,5 +223,6 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { } return types.NewGenesisState(params, usdxMintingGats, hardSupplyGats, - hardBorrowGats, hardDelegatorGats, swapGats, synchronizedUsdxClaims, synchronizedHardClaims) + hardBorrowGats, delegatorGats, swapGats, synchronizedUsdxClaims, + synchronizedHardClaims, synchronizedDelegatorClaims) } diff --git a/x/incentive/genesis_test.go b/x/incentive/genesis_test.go index ce5bb83a..17f66aae 100644 --- a/x/incentive/genesis_test.go +++ b/x/incentive/genesis_test.go @@ -76,6 +76,7 @@ func (suite *GenesisTestSuite) SetupTest() { incentive.DefaultGenesisAccumulationTimes, incentive.DefaultUSDXClaims, incentive.DefaultHardClaims, + incentive.DefaultDelegatorClaims, ) tApp.InitializeFromGenesisStatesWithTime( suite.genesisTime, diff --git a/x/incentive/handler.go b/x/incentive/handler.go index 7f26f512..a5c02ebf 100644 --- a/x/incentive/handler.go +++ b/x/incentive/handler.go @@ -21,6 +21,10 @@ func NewHandler(k keeper.Keeper) sdk.Handler { return handleMsgClaimHardReward(ctx, k, msg) case types.MsgClaimHardRewardVVesting: return handleMsgClaimHardRewardVVesting(ctx, k, msg) + case types.MsgClaimDelegatorReward: + return handleMsgClaimDelegatorReward(ctx, k, msg) + case types.MsgClaimDelegatorRewardVVesting: + return handleMsgClaimDelegatorRewardVVesting(ctx, k, msg) default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) } @@ -69,3 +73,25 @@ func handleMsgClaimHardRewardVVesting(ctx sdk.Context, k keeper.Keeper, msg type Events: ctx.EventManager().Events(), }, nil } + +func handleMsgClaimDelegatorReward(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimDelegatorReward) (*sdk.Result, error) { + + err := k.ClaimDelegatorReward(ctx, msg.Sender, types.MultiplierName(msg.MultiplierName)) + if err != nil { + return nil, err + } + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil +} + +func handleMsgClaimDelegatorRewardVVesting(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimDelegatorRewardVVesting) (*sdk.Result, error) { + + err := k.ClaimDelegatorRewardVVesting(ctx, msg.Sender, msg.Receiver, types.MultiplierName(msg.MultiplierName)) + if err != nil { + return nil, err + } + return &sdk.Result{ + Events: ctx.EventManager().Events(), + }, nil +} diff --git a/x/incentive/handler_test.go b/x/incentive/handler_test.go index e6e7ae45..ba8b9845 100644 --- a/x/incentive/handler_test.go +++ b/x/incentive/handler_test.go @@ -59,6 +59,7 @@ func (suite *HandlerTestSuite) SetupTest() { incentive.DefaultGenesisAccumulationTimes, incentive.DefaultUSDXClaims, incentive.DefaultHardClaims, + incentive.DefaultDelegatorClaims, ) tApp.InitializeFromGenesisStates(authGS, app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(incentiveGS)}, NewCDPGenStateMulti(), NewPricefeedGenStateMulti()) @@ -92,7 +93,7 @@ func (suite *HandlerTestSuite) addHardLiquidityProviderClaim() { rewardPeriod := types.RewardIndexes{types.NewRewardIndex("bnb-s", sdk.ZeroDec())} multiRewardIndex := types.NewMultiRewardIndex("bnb-s", rewardPeriod) multiRewardIndexes := types.MultiRewardIndexes{multiRewardIndex} - c1 := incentive.NewHardLiquidityProviderClaim(suite.addrs[0], cs(c("ukava", 1000000)), multiRewardIndexes, multiRewardIndexes, multiRewardIndexes) + c1 := incentive.NewHardLiquidityProviderClaim(suite.addrs[0], cs(c("ukava", 1000000)), multiRewardIndexes, multiRewardIndexes) suite.NotPanics(func() { suite.keeper.SetHardLiquidityProviderClaim(suite.ctx, c1) }) @@ -108,6 +109,8 @@ func (suite *HandlerTestSuite) addUSDXMintingClaim() { }) } +// TODO: add tests + func TestHandlerTestSuite(t *testing.T) { suite.Run(t, new(HandlerTestSuite)) } diff --git a/x/incentive/keeper/hooks.go b/x/incentive/keeper/hooks.go index 84fcf751..2264637e 100644 --- a/x/incentive/keeper/hooks.go +++ b/x/incentive/keeper/hooks.go @@ -89,13 +89,13 @@ When delegated tokens (to bonded validators) are changed: // BeforeDelegationCreated runs before a delegation is created func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { // Add a claim if one doesn't exist, otherwise sync the existing. - h.k.InitializeHardDelegatorReward(ctx, delAddr) + h.k.InitializeDelegatorReward(ctx, delAddr) } // BeforeDelegationSharesModified runs before an existing delegation is modified func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { // Sync rewards based on total delegated to bonded validators. - h.k.SynchronizeHardDelegatorRewards(ctx, delAddr, nil, false) + h.k.SynchronizeDelegatorRewards(ctx, delAddr, nil, false) } // BeforeValidatorSlashed is called before a validator is slashed @@ -104,7 +104,7 @@ func (h Hooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, f // Sync all claims for users delegated to this validator. // For each claim, sync based on the total delegated to bonded validators. for _, delegation := range h.k.stakingKeeper.GetValidatorDelegations(ctx, valAddr) { - h.k.SynchronizeHardDelegatorRewards(ctx, delegation.DelegatorAddress, nil, false) + h.k.SynchronizeDelegatorRewards(ctx, delegation.DelegatorAddress, nil, false) } } @@ -115,7 +115,7 @@ func (h Hooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAd // For each claim, sync based on the total delegated to bonded validators, and also delegations to valAddr. // valAddr's status has just been set to Unbonding, but we want to include delegations to it in the sync. for _, delegation := range h.k.stakingKeeper.GetValidatorDelegations(ctx, valAddr) { - h.k.SynchronizeHardDelegatorRewards(ctx, delegation.DelegatorAddress, valAddr, true) + h.k.SynchronizeDelegatorRewards(ctx, delegation.DelegatorAddress, valAddr, true) } } @@ -126,7 +126,7 @@ func (h Hooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, v // For each claim, sync based on the total delegated to bonded validators, except for delegations to valAddr. // valAddr's status has just been set to Bonded, but we don't want to include delegations to it in the sync for _, delegation := range h.k.stakingKeeper.GetValidatorDelegations(ctx, valAddr) { - h.k.SynchronizeHardDelegatorRewards(ctx, delegation.DelegatorAddress, valAddr, false) + h.k.SynchronizeDelegatorRewards(ctx, delegation.DelegatorAddress, valAddr, false) } } diff --git a/x/incentive/keeper/integration_test.go b/x/incentive/keeper/integration_test.go index fbf2d1c9..2c2c5734 100644 --- a/x/incentive/keeper/integration_test.go +++ b/x/incentive/keeper/integration_test.go @@ -279,10 +279,10 @@ func (builder IncentiveGenesisBuilder) WithSimpleSupplyRewardPeriod(ctype string )) } func (builder IncentiveGenesisBuilder) WithInitializedDelegatorRewardPeriod(period types.MultiRewardPeriod) IncentiveGenesisBuilder { - builder.Params.HardDelegatorRewardPeriods = append(builder.Params.HardDelegatorRewardPeriods, period) + builder.Params.DelegatorRewardPeriods = append(builder.Params.DelegatorRewardPeriods, period) accumulationTimeForPeriod := types.NewGenesisAccumulationTime(period.CollateralType, builder.genesisTime) - builder.HardDelegatorAccumulationTimes = append(builder.HardDelegatorAccumulationTimes, accumulationTimeForPeriod) + builder.DelegatorAccumulationTimes = append(builder.DelegatorAccumulationTimes, accumulationTimeForPeriod) return builder } diff --git a/x/incentive/keeper/keeper.go b/x/incentive/keeper/keeper.go index 7be70d51..7ef1c6fa 100644 --- a/x/incentive/keeper/keeper.go +++ b/x/incentive/keeper/keeper.go @@ -210,6 +210,55 @@ func (k Keeper) GetAllHardLiquidityProviderClaims(ctx sdk.Context) types.HardLiq return cs } +// GetDelegatorClaim returns the claim in the store corresponding the the input address collateral type and id and a boolean for if the claim was found +func (k Keeper) GetDelegatorClaim(ctx sdk.Context, addr sdk.AccAddress) (types.DelegatorClaim, bool) { + store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorClaimKeyPrefix) + bz := store.Get(addr) + if bz == nil { + return types.DelegatorClaim{}, false + } + var c types.DelegatorClaim + k.cdc.MustUnmarshalBinaryBare(bz, &c) + return c, true +} + +// SetDelegatorClaim sets the claim in the store corresponding to the input address, collateral type, and id +func (k Keeper) SetDelegatorClaim(ctx sdk.Context, c types.DelegatorClaim) { + store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorClaimKeyPrefix) + bz := k.cdc.MustMarshalBinaryBare(c) + store.Set(c.Owner, bz) +} + +// DeleteDelegatorClaim deletes the claim in the store corresponding to the input address, collateral type, and id +func (k Keeper) DeleteDelegatorClaim(ctx sdk.Context, owner sdk.AccAddress) { + store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorClaimKeyPrefix) + store.Delete(owner) +} + +// IterateDelegatorClaims iterates over all claim objects in the store and preforms a callback function +func (k Keeper) IterateDelegatorClaims(ctx sdk.Context, cb func(c types.DelegatorClaim) (stop bool)) { + store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorClaimKeyPrefix) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var c types.DelegatorClaim + k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &c) + if cb(c) { + break + } + } +} + +// GetAllDelegatorClaims returns all DelegatorClaim objects in the store +func (k Keeper) GetAllDelegatorClaims(ctx sdk.Context) types.DelegatorClaims { + cs := types.DelegatorClaims{} + k.IterateDelegatorClaims(ctx, func(c types.DelegatorClaim) (stop bool) { + cs = append(cs, c) + return false + }) + return cs +} + // SetHardSupplyRewardIndexes sets the current reward indexes for an individual denom func (k Keeper) SetHardSupplyRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) { store := prefix.NewStore(ctx.KVStore(k.key), types.HardSupplyRewardIndexesKeyPrefix) @@ -276,9 +325,9 @@ func (k Keeper) IterateHardBorrowRewardIndexes(ctx sdk.Context, cb func(denom st } } -// GetHardDelegatorRewardIndexes gets the current reward indexes for an individual denom -func (k Keeper) GetHardDelegatorRewardIndexes(ctx sdk.Context, denom string) (types.RewardIndexes, bool) { - store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix) +// GetDelegatorRewardIndexes gets the current reward indexes for an individual denom +func (k Keeper) GetDelegatorRewardIndexes(ctx sdk.Context, denom string) (types.RewardIndexes, bool) { + store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorRewardIndexesKeyPrefix) bz := store.Get([]byte(denom)) if bz == nil { return types.RewardIndexes{}, false @@ -288,16 +337,16 @@ func (k Keeper) GetHardDelegatorRewardIndexes(ctx sdk.Context, denom string) (ty return rewardIndexes, true } -// SetHardDelegatorRewardIndexes sets the current reward indexes for an individual denom -func (k Keeper) SetHardDelegatorRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) { - store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix) +// SetDelegatorRewardIndexes sets the current reward indexes for an individual denom +func (k Keeper) SetDelegatorRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) { + store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorRewardIndexesKeyPrefix) bz := k.cdc.MustMarshalBinaryBare(indexes) store.Set([]byte(denom), bz) } -// IterateHardDelegatorRewardIndexes iterates over all Delegator reward index objects in the store and preforms a callback function -func (k Keeper) IterateHardDelegatorRewardIndexes(ctx sdk.Context, cb func(denom string, indexes types.RewardIndexes) (stop bool)) { - store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix) +// IterateDelegatorRewardIndexes iterates over all delegator reward index objects in the store and preforms a callback function +func (k Keeper) IterateDelegatorRewardIndexes(ctx sdk.Context, cb func(denom string, indexes types.RewardIndexes) (stop bool)) { + store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorRewardIndexesKeyPrefix) iterator := sdk.KVStorePrefixIterator(store, []byte{}) defer iterator.Close() for ; iterator.Valid(); iterator.Next() { @@ -343,9 +392,9 @@ func (k Keeper) SetPreviousHardBorrowRewardAccrualTime(ctx sdk.Context, denom st store.Set([]byte(denom), k.cdc.MustMarshalBinaryBare(blockTime)) } -// GetPreviousHardDelegatorRewardAccrualTime returns the last time a denom accrued Hard protocol delegator rewards -func (k Keeper) GetPreviousHardDelegatorRewardAccrualTime(ctx sdk.Context, denom string) (blockTime time.Time, found bool) { - store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix) +// GetPreviousDelegatorRewardAccrualTime returns the last time a denom accrued protocol delegator rewards +func (k Keeper) GetPreviousDelegatorRewardAccrualTime(ctx sdk.Context, denom string) (blockTime time.Time, found bool) { + store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousDelegatorRewardAccrualTimeKeyPrefix) bz := store.Get([]byte(denom)) if bz == nil { return time.Time{}, false @@ -354,9 +403,9 @@ func (k Keeper) GetPreviousHardDelegatorRewardAccrualTime(ctx sdk.Context, denom return blockTime, true } -// SetPreviousHardDelegatorRewardAccrualTime sets the last time a denom accrued Hard protocol delegator rewards -func (k Keeper) SetPreviousHardDelegatorRewardAccrualTime(ctx sdk.Context, denom string, blockTime time.Time) { - store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix) +// SetPreviousDelegatorRewardAccrualTime sets the last time a denom accrued protocol delegator rewards +func (k Keeper) SetPreviousDelegatorRewardAccrualTime(ctx sdk.Context, denom string, blockTime time.Time) { + store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousDelegatorRewardAccrualTimeKeyPrefix) store.Set([]byte(denom), k.cdc.MustMarshalBinaryBare(blockTime)) } diff --git a/x/incentive/keeper/params.go b/x/incentive/keeper/params.go index 4f499525..587f1d5d 100644 --- a/x/incentive/keeper/params.go +++ b/x/incentive/keeper/params.go @@ -53,10 +53,10 @@ func (k Keeper) GetHardBorrowRewardPeriods(ctx sdk.Context, denom string) (types return types.MultiRewardPeriod{}, false } -// GetHardDelegatorRewardPeriod returns the reward period with the specified collateral type if it's found in the params -func (k Keeper) GetHardDelegatorRewardPeriods(ctx sdk.Context, denom string) (types.MultiRewardPeriod, bool) { +// GetDelegatorRewardPeriods returns the reward period with the specified collateral type if it's found in the params +func (k Keeper) GetDelegatorRewardPeriods(ctx sdk.Context, denom string) (types.MultiRewardPeriod, bool) { params := k.GetParams(ctx) - for _, rp := range params.HardDelegatorRewardPeriods { + for _, rp := range params.DelegatorRewardPeriods { if rp.CollateralType == denom { return rp, true } diff --git a/x/incentive/keeper/payout.go b/x/incentive/keeper/payout.go index 6bf9b7a1..f0195f07 100644 --- a/x/incentive/keeper/payout.go +++ b/x/incentive/keeper/payout.go @@ -193,7 +193,7 @@ func (k Keeper) ClaimHardReward(ctx sdk.Context, addr sdk.AccAddress, multiplier return nil } -// ClaimHardReward sends the reward amount to the input address and zero's out the claim in the store +// ClaimHardRewardVVesting sends the reward amount to the input address and zero's out the claim in the store func (k Keeper) ClaimHardRewardVVesting(ctx sdk.Context, owner, receiver sdk.AccAddress, multiplierName types.MultiplierName) error { _, found := k.GetHardLiquidityProviderClaim(ctx, owner) if !found { @@ -261,6 +261,129 @@ func (k Keeper) ClaimHardRewardVVesting(ctx sdk.Context, owner, receiver sdk.Acc return nil } +// ClaimDelegatorReward sends the reward amount to the input address and zero's out the delegator claim in the store +func (k Keeper) ClaimDelegatorReward(ctx sdk.Context, addr sdk.AccAddress, multiplierName types.MultiplierName) error { + claim, found := k.GetDelegatorClaim(ctx, addr) + if !found { + return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", addr) + } + + multiplier, found := k.GetMultiplier(ctx, multiplierName) + if !found { + return sdkerrors.Wrapf(types.ErrInvalidMultiplier, string(multiplierName)) + } + + claimEnd := k.GetClaimEnd(ctx) + + if ctx.BlockTime().After(claimEnd) { + return sdkerrors.Wrapf(types.ErrClaimExpired, "block time %s > claim end time %s", ctx.BlockTime(), claimEnd) + } + + syncedClaim, err := k.SynchronizeDelegatorClaim(ctx, claim) + if !found { + return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", addr) + } + + var rewardCoins sdk.Coins + for _, coin := range syncedClaim.Reward { + rewardAmount := coin.Amount.ToDec().Mul(multiplier.Factor).RoundInt() + if rewardAmount.IsZero() { + continue + } + rewardCoins = append(rewardCoins, sdk.NewCoin(coin.Denom, rewardAmount)) + } + if rewardCoins.IsZero() { + return types.ErrZeroClaim + } + length, err := k.GetPeriodLength(ctx, multiplier) + if err != nil { + return err + } + + err = k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, addr, rewardCoins, length) + if err != nil { + return err + } + + k.ZeroDelegatorClaim(ctx, syncedClaim) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeClaim, + sdk.NewAttribute(types.AttributeKeyClaimedBy, syncedClaim.GetOwner().String()), + sdk.NewAttribute(types.AttributeKeyClaimAmount, syncedClaim.GetReward().String()), + sdk.NewAttribute(types.AttributeKeyClaimType, syncedClaim.GetType()), + ), + ) + return nil +} + +// ClaimDelegatorRewardVVesting sends the reward amount to the input address and zero's out the claim in the store +func (k Keeper) ClaimDelegatorRewardVVesting(ctx sdk.Context, owner, receiver sdk.AccAddress, multiplierName types.MultiplierName) error { + claim, found := k.GetDelegatorClaim(ctx, owner) + if !found { + return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", owner) + } + + acc := k.accountKeeper.GetAccount(ctx, owner) + if acc == nil { + return sdkerrors.Wrapf(types.ErrAccountNotFound, "address not found: %s", owner) + } + _, ok := acc.(*validatorvesting.ValidatorVestingAccount) + if !ok { + return sdkerrors.Wrapf(types.ErrInvalidAccountType, "owner account must be validator vesting account %s", owner) + } + + multiplier, found := k.GetMultiplier(ctx, multiplierName) + if !found { + return sdkerrors.Wrapf(types.ErrInvalidMultiplier, string(multiplierName)) + } + + claimEnd := k.GetClaimEnd(ctx) + + if ctx.BlockTime().After(claimEnd) { + return sdkerrors.Wrapf(types.ErrClaimExpired, "block time %s > claim end time %s", ctx.BlockTime(), claimEnd) + } + + syncedClaim, err := k.SynchronizeDelegatorClaim(ctx, claim) + if !found { + return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", owner) + } + + var rewardCoins sdk.Coins + for _, coin := range syncedClaim.Reward { + rewardAmount := coin.Amount.ToDec().Mul(multiplier.Factor).RoundInt() + if rewardAmount.IsZero() { + continue + } + rewardCoins = append(rewardCoins, sdk.NewCoin(coin.Denom, rewardAmount)) + } + if rewardCoins.IsZero() { + return types.ErrZeroClaim + } + length, err := k.GetPeriodLength(ctx, multiplier) + if err != nil { + return err + } + + err = k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, receiver, rewardCoins, length) + if err != nil { + return err + } + + k.ZeroDelegatorClaim(ctx, syncedClaim) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeClaim, + sdk.NewAttribute(types.AttributeKeyClaimedBy, syncedClaim.GetOwner().String()), + sdk.NewAttribute(types.AttributeKeyClaimAmount, syncedClaim.GetReward().String()), + sdk.NewAttribute(types.AttributeKeyClaimType, syncedClaim.GetType()), + ), + ) + return nil +} + // SendTimeLockedCoinsToAccount sends time-locked coins from the input module account to the recipient. If the recipients account is not a vesting account and the input length is greater than zero, the recipient account is converted to a periodic vesting account and the coins are added to the vesting balance as a vesting period with the input length. func (k Keeper) SendTimeLockedCoinsToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, length int64) error { macc := k.supplyKeeper.GetModuleAccount(ctx, senderModule) diff --git a/x/incentive/keeper/querier.go b/x/incentive/keeper/querier.go index dcda0eeb..ff593f5c 100644 --- a/x/incentive/keeper/querier.go +++ b/x/incentive/keeper/querier.go @@ -25,6 +25,10 @@ func NewQuerier(k Keeper) sdk.Querier { return queryGetUSDXMintingRewards(ctx, req, k) case types.QueryGetUSDXMintingRewardsUnsynced: return queryGetUSDXMintingRewardsUnsynced(ctx, req, k) + case types.QueryGetDelegatorRewards: + return queryGetDelegatorRewards(ctx, req, k) + case types.QueryGetDelegatorRewardsUnsynced: + return queryGetDelegatorRewardsUnsynced(ctx, req, k) case types.QueryGetRewardFactors: return queryGetRewardFactors(ctx, req, k) default: @@ -198,6 +202,82 @@ func queryGetUSDXMintingRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery, return bz, nil } +func queryGetDelegatorRewards(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { + var params types.QueryDelegatorRewardsParams + err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) + } + owner := len(params.Owner) > 0 + + var delegatorClaims types.DelegatorClaims + switch { + case owner: + delegatorClaim, foundDelegatorClaim := k.GetDelegatorClaim(ctx, params.Owner) + if foundDelegatorClaim { + delegatorClaims = append(delegatorClaims, delegatorClaim) + } + default: + delegatorClaims = k.GetAllDelegatorClaims(ctx) + } + + var paginatedDelegatorClaims types.DelegatorClaims + startH, endH := client.Paginate(len(delegatorClaims), params.Page, params.Limit, 100) + if startH < 0 || endH < 0 { + paginatedDelegatorClaims = types.DelegatorClaims{} + } else { + paginatedDelegatorClaims = delegatorClaims[startH:endH] + } + + var augmentedDelegatorClaims types.DelegatorClaims + for _, claim := range paginatedDelegatorClaims { + augmentedClaim := k.SimulateDelegatorSynchronization(ctx, claim) + augmentedDelegatorClaims = append(augmentedDelegatorClaims, augmentedClaim) + } + + // Marshal Hard claims + bz, err := codec.MarshalJSONIndent(k.cdc, augmentedDelegatorClaims) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) + } + return bz, nil +} + +func queryGetDelegatorRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { + var params types.QueryDelegatorRewardsUnsyncedParams + err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) + } + owner := len(params.Owner) > 0 + + var delegatorClaims types.DelegatorClaims + switch { + case owner: + delegatorClaim, foundHardClaim := k.GetDelegatorClaim(ctx, params.Owner) + if foundHardClaim { + delegatorClaims = append(delegatorClaims, delegatorClaim) + } + default: + delegatorClaims = k.GetAllDelegatorClaims(ctx) + } + + var paginatedDelegatorClaims types.DelegatorClaims + startH, endH := client.Paginate(len(delegatorClaims), params.Page, params.Limit, 100) + if startH < 0 || endH < 0 { + paginatedDelegatorClaims = types.DelegatorClaims{} + } else { + paginatedDelegatorClaims = delegatorClaims[startH:endH] + } + + // Marshal Hard claims + bz, err := codec.MarshalJSONIndent(k.cdc, paginatedDelegatorClaims) + if err != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error()) + } + return bz, nil +} + func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) { var params types.QueryRewardFactorsParams err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) @@ -223,9 +303,9 @@ func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([] if found { rewardFactor.HardBorrowRewardFactors = hardBorrowRewardIndexes } - hardDelegatorRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, params.Denom) + delegatorRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, params.Denom) if found { - rewardFactor.HardDelegatorRewardFactors = hardDelegatorRewardIndexes + rewardFactor.DelegatorRewardFactors = delegatorRewardIndexes } rewardFactors = append(rewardFactors, rewardFactor) } else { @@ -262,13 +342,13 @@ func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([] return false }) - // Populate mapping with Hard delegator reward factors - k.IterateHardDelegatorRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) { + // Populate mapping with delegator reward factors + k.IterateDelegatorRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) { rewardFactor, ok := rewardFactorMap[denom] if !ok { - rewardFactor = types.RewardFactor{Denom: denom, HardDelegatorRewardFactors: indexes} + rewardFactor = types.RewardFactor{Denom: denom, DelegatorRewardFactors: indexes} } else { - rewardFactor.HardDelegatorRewardFactors = indexes + rewardFactor.DelegatorRewardFactors = indexes } rewardFactorMap[denom] = rewardFactor return false diff --git a/x/incentive/keeper/rewards_borrow.go b/x/incentive/keeper/rewards_borrow.go index eeff88ea..7ca2ba37 100644 --- a/x/incentive/keeper/rewards_borrow.go +++ b/x/incentive/keeper/rewards_borrow.go @@ -81,7 +81,7 @@ func (k Keeper) AccumulateHardBorrowRewards(ctx sdk.Context, rewardPeriod types. func (k Keeper) InitializeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Borrow) { claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower) if !found { - claim = types.NewHardLiquidityProviderClaim(borrow.Borrower, sdk.Coins{}, nil, nil, nil) + claim = types.NewHardLiquidityProviderClaim(borrow.Borrower, sdk.Coins{}, nil, nil) } var borrowRewardIndexes types.MultiRewardIndexes @@ -142,7 +142,7 @@ func (k Keeper) SynchronizeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Bo func (k Keeper) UpdateHardBorrowIndexDenoms(ctx sdk.Context, borrow hardtypes.Borrow) { claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower) if !found { - claim = types.NewHardLiquidityProviderClaim(borrow.Borrower, sdk.Coins{}, nil, nil, nil) + claim = types.NewHardLiquidityProviderClaim(borrow.Borrower, sdk.Coins{}, nil, nil) } borrowDenoms := getDenoms(borrow.Amount) diff --git a/x/incentive/keeper/rewards_borrow_init_test.go b/x/incentive/keeper/rewards_borrow_init_test.go index 01f88b83..296041e2 100644 --- a/x/incentive/keeper/rewards_borrow_init_test.go +++ b/x/incentive/keeper/rewards_borrow_init_test.go @@ -36,7 +36,7 @@ func (suite *InitializeHardBorrowRewardTests) TestClaimIndexesAreSetWhenClaimExi // which means UpdateHardBorrowIndexDenoms was called and should have remove indexes. BorrowRewardIndexes: types.MultiRewardIndexes{}, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := nonEmptyMultiRewardIndexes suite.storeGlobalBorrowIndexes(globalIndexes) diff --git a/x/incentive/keeper/rewards_borrow_sync_test.go b/x/incentive/keeper/rewards_borrow_sync_test.go index bf3e8004..3be2ae46 100644 --- a/x/incentive/keeper/rewards_borrow_sync_test.go +++ b/x/incentive/keeper/rewards_borrow_sync_test.go @@ -39,7 +39,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestClaimIndexesAreUpdatedWhenGlo }, BorrowRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := increaseAllRewardFactors(nonEmptyMultiRewardIndexes) suite.storeGlobalBorrowIndexes(globalIndexes) @@ -64,7 +64,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestClaimIndexesAreUnchangedWhenG }, BorrowRewardIndexes: unchangingIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) suite.storeGlobalBorrowIndexes(unchangingIndexes) @@ -88,7 +88,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestClaimIndexesAreUpdatedWhenNew }, BorrowRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := appendUniqueMultiRewardIndex(nonEmptyMultiRewardIndexes) suite.storeGlobalBorrowIndexes(globalIndexes) @@ -114,7 +114,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestClaimIndexesAreUpdatedWhenNew }, BorrowRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := appendUniqueRewardIndexToFirstItem(nonEmptyMultiRewardIndexes) suite.storeGlobalBorrowIndexes(globalIndexes) @@ -155,7 +155,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestRewardIsIncrementedWhenGlobal }, }, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) suite.storeGlobalBorrowIndexes(types.MultiRewardIndexes{ { @@ -206,7 +206,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestRewardIsIncrementedWhenNewRew }, }, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := types.MultiRewardIndexes{ { @@ -269,7 +269,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestRewardIsIncrementedWhenNewRew }, }, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := types.MultiRewardIndexes{ { diff --git a/x/incentive/keeper/rewards_borrow_update_test.go b/x/incentive/keeper/rewards_borrow_update_test.go index 00a4e0b8..0cfa7fb2 100644 --- a/x/incentive/keeper/rewards_borrow_update_test.go +++ b/x/incentive/keeper/rewards_borrow_update_test.go @@ -33,7 +33,7 @@ func (suite *UpdateHardBorrowIndexDenomsTests) TestClaimIndexesAreRemovedForDeno }, BorrowRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) suite.storeGlobalBorrowIndexes(claim.BorrowRewardIndexes) // remove one denom from the indexes already in the borrow @@ -56,7 +56,7 @@ func (suite *UpdateHardBorrowIndexDenomsTests) TestClaimIndexesAreAddedForNewlyB }, BorrowRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := appendUniqueMultiRewardIndex(claim.BorrowRewardIndexes) suite.storeGlobalBorrowIndexes(globalIndexes) @@ -78,7 +78,7 @@ func (suite *UpdateHardBorrowIndexDenomsTests) TestClaimIndexesAreUnchangedWhenB }, BorrowRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) // Set global indexes with same denoms but different values. // UpdateHardBorrowIndexDenoms should ignore the new values. suite.storeGlobalBorrowIndexes(increaseAllRewardFactors(claim.BorrowRewardIndexes)) @@ -101,7 +101,7 @@ func (suite *UpdateHardBorrowIndexDenomsTests) TestEmptyClaimIndexesAreAddedForN }, BorrowRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) suite.storeGlobalBorrowIndexes(claim.BorrowRewardIndexes) // add a denom to the borrowed amount that is not in the global or claim's indexes diff --git a/x/incentive/keeper/rewards_delegator.go b/x/incentive/keeper/rewards_delegator.go index beaf6cc1..e83e3fa2 100644 --- a/x/incentive/keeper/rewards_delegator.go +++ b/x/incentive/keeper/rewards_delegator.go @@ -8,11 +8,11 @@ import ( "github.com/kava-labs/kava/x/incentive/types" ) -// AccumulateHardDelegatorRewards updates the rewards accumulated for the input reward period -func (k Keeper) AccumulateHardDelegatorRewards(ctx sdk.Context, rewardPeriods types.MultiRewardPeriod) error { - previousAccrualTime, found := k.GetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType) +// AccumulateDelegatorRewards updates the rewards accumulated for the input reward period +func (k Keeper) AccumulateDelegatorRewards(ctx sdk.Context, rewardPeriods types.MultiRewardPeriod) error { + previousAccrualTime, found := k.GetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType) if !found { - k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) + k.SetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) return nil } timeElapsed := CalculateTimeElapsed(rewardPeriods.Start, rewardPeriods.End, ctx.BlockTime(), previousAccrualTime) @@ -20,23 +20,23 @@ func (k Keeper) AccumulateHardDelegatorRewards(ctx sdk.Context, rewardPeriods ty return nil } if rewardPeriods.RewardsPerSecond.IsZero() { - k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) + k.SetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) return nil } totalBonded := k.stakingKeeper.TotalBondedTokens(ctx).ToDec() if totalBonded.IsZero() { - k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) + k.SetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) return nil } - previousRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType) + previousRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType) if !found { for _, rewardCoin := range rewardPeriods.RewardsPerSecond { rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec()) previousRewardIndexes = append(previousRewardIndexes, rewardIndex) } - k.SetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, previousRewardIndexes) + k.SetDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, previousRewardIndexes) } newRewardIndexes := previousRewardIndexes @@ -58,42 +58,53 @@ func (k Keeper) AccumulateHardDelegatorRewards(ctx sdk.Context, rewardPeriods ty newRewardIndexes = append(newRewardIndexes, newRewardIndex) } } - k.SetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, newRewardIndexes) - k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) + k.SetDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, newRewardIndexes) + k.SetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) return nil } -// InitializeHardDelegatorReward initializes the delegator reward index of a hard claim -func (k Keeper) InitializeHardDelegatorReward(ctx sdk.Context, delegator sdk.AccAddress) { - claim, found := k.GetHardLiquidityProviderClaim(ctx, delegator) +// InitializeDelegatorReward initializes the reward index of a delegator claim +func (k Keeper) InitializeDelegatorReward(ctx sdk.Context, delegator sdk.AccAddress) { + claim, found := k.GetDelegatorClaim(ctx, delegator) if !found { - claim = types.NewHardLiquidityProviderClaim(delegator, sdk.Coins{}, nil, nil, nil) + claim = types.NewDelegatorClaim(delegator, sdk.Coins{}, nil) } else { - k.SynchronizeHardDelegatorRewards(ctx, delegator, nil, false) - claim, _ = k.GetHardLiquidityProviderClaim(ctx, delegator) + k.SynchronizeDelegatorRewards(ctx, delegator, nil, false) + claim, _ = k.GetDelegatorClaim(ctx, delegator) } - var delegatorRewardIndexes types.MultiRewardIndexes - globalRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, types.BondDenom) + var rewardIndexes types.MultiRewardIndexes + globalRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, types.BondDenom) if !found { globalRewardIndexes = types.RewardIndexes{} } - delegatorRewardIndexes = delegatorRewardIndexes.With(types.BondDenom, globalRewardIndexes) - - claim.DelegatorRewardIndexes = delegatorRewardIndexes - k.SetHardLiquidityProviderClaim(ctx, claim) + rewardIndexes = rewardIndexes.With(types.BondDenom, globalRewardIndexes) + claim.RewardIndexes = rewardIndexes + k.SetDelegatorClaim(ctx, claim) } -// SynchronizeHardDelegatorRewards updates the claim object by adding any accumulated rewards, and setting the reward indexes to the global values. +// SynchronizeDelegatorClaim is a wrapper around SynchronizeDelegatorRewards that returns the synced claim +func (k Keeper) SynchronizeDelegatorClaim(ctx sdk.Context, claim types.DelegatorClaim) (types.DelegatorClaim, error) { + k.SynchronizeDelegatorRewards(ctx, claim.Owner, nil, false) + + claim, found := k.GetDelegatorClaim(ctx, claim.Owner) + if !found { + return claim, types.ErrClaimNotFound + } + return claim, nil +} + +// SynchronizeDelegatorRewards updates the claim object by adding any accumulated rewards, and setting the reward indexes to the global values. // valAddr and shouldIncludeValidator are used to ignore or include delegations to a particular validator when summing up the total delegation. -// Normally only delegations to Bonded validators are included in the total. This is needed as staking hooks are sometimes called on the wrong side of a validator's state update (from this module's perspective). -func (k Keeper) SynchronizeHardDelegatorRewards(ctx sdk.Context, delegator sdk.AccAddress, valAddr sdk.ValAddress, shouldIncludeValidator bool) { - claim, found := k.GetHardLiquidityProviderClaim(ctx, delegator) +// Normally only delegations to Bonded validators are included in the total. This is needed as staking hooks are sometimes called on the wrong +// side of a validator's state update (from this module's perspective). +func (k Keeper) SynchronizeDelegatorRewards(ctx sdk.Context, delegator sdk.AccAddress, valAddr sdk.ValAddress, shouldIncludeValidator bool) { + claim, found := k.GetDelegatorClaim(ctx, delegator) if !found { return } - globalRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, types.BondDenom) + globalRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, types.BondDenom) if !found { // The global factor is only not found if // - the bond denom has not started accumulating rewards yet (either there is no reward specified in params, or the reward start time hasn't been hit) @@ -104,7 +115,7 @@ func (k Keeper) SynchronizeHardDelegatorRewards(ctx sdk.Context, delegator sdk.A return } - userRewardIndexes, found := claim.DelegatorRewardIndexes.Get(types.BondDenom) + userRewardIndexes, found := claim.RewardIndexes.Get(types.BondDenom) if !found { // Normally the reward indexes should always be found. // However if there were no delegator rewards (ie no reward period in params) then a reward period is added, existing claims will not have the factor. @@ -122,8 +133,8 @@ func (k Keeper) SynchronizeHardDelegatorRewards(ctx sdk.Context, delegator sdk.A } claim.Reward = claim.Reward.Add(rewardsEarned...) - claim.DelegatorRewardIndexes = claim.DelegatorRewardIndexes.With(types.BondDenom, globalRewardIndexes) - k.SetHardLiquidityProviderClaim(ctx, claim) + claim.RewardIndexes = claim.RewardIndexes.With(types.BondDenom, globalRewardIndexes) + k.SetDelegatorClaim(ctx, claim) } func (k Keeper) GetTotalDelegated(ctx sdk.Context, delegator sdk.AccAddress, valAddr sdk.ValAddress, shouldIncludeValidator bool) sdk.Dec { @@ -162,3 +173,63 @@ func (k Keeper) GetTotalDelegated(ctx sdk.Context, delegator sdk.AccAddress, val } return totalDelegated } + +// ZeroDelegatorClaim zeroes out the claim object's rewards and returns the updated claim object +func (k Keeper) ZeroDelegatorClaim(ctx sdk.Context, claim types.DelegatorClaim) types.DelegatorClaim { + claim.Reward = sdk.NewCoins() + k.SetDelegatorClaim(ctx, claim) + return claim +} + +// SimulateDelegatorSynchronization calculates a user's outstanding delegator rewards by simulating reward synchronization +func (k Keeper) SimulateDelegatorSynchronization(ctx sdk.Context, claim types.DelegatorClaim) types.DelegatorClaim { + for _, ri := range claim.RewardIndexes { + // For each Delegator reward index (there's only one: the bond denom 'ukava') + globalRewardIndexes, foundGlobalRewardIndexes := k.GetDelegatorRewardIndexes(ctx, ri.CollateralType) + if !foundGlobalRewardIndexes { + continue + } + + userRewardIndexes, foundUserRewardIndexes := claim.RewardIndexes.GetRewardIndex(ri.CollateralType) + if !foundUserRewardIndexes { + continue + } + + userRewardIndexIndex, foundUserRewardIndexIndex := claim.RewardIndexes.GetRewardIndexIndex(ri.CollateralType) + if !foundUserRewardIndexIndex { + continue + } + + amtDelegated := k.GetTotalDelegated(ctx, claim.GetOwner(), sdk.ValAddress(claim.Owner.String()), true) + + for _, globalRewardIndex := range globalRewardIndexes { + userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType) + if !foundUserRewardIndex { + userRewardIndex = types.NewRewardIndex(globalRewardIndex.CollateralType, sdk.ZeroDec()) + userRewardIndexes.RewardIndexes = append(userRewardIndexes.RewardIndexes, userRewardIndex) + claim.RewardIndexes[userRewardIndexIndex].RewardIndexes = append(claim.RewardIndexes[userRewardIndexIndex].RewardIndexes, userRewardIndex) + } + + globalRewardFactor := globalRewardIndex.RewardFactor + userRewardFactor := userRewardIndex.RewardFactor + rewardsAccumulatedFactor := globalRewardFactor.Sub(userRewardFactor) + if rewardsAccumulatedFactor.IsZero() { + continue + } + + rewardsEarned := rewardsAccumulatedFactor.Mul(amtDelegated).RoundInt() + if rewardsEarned.IsZero() || rewardsEarned.IsNegative() { + continue + } + + factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType) + if !foundFactorIndex { + continue + } + claim.RewardIndexes[userRewardIndexIndex].RewardIndexes[factorIndex].RewardFactor = globalRewardIndex.RewardFactor + newRewardsCoin := sdk.NewCoin(userRewardIndex.CollateralType, rewardsEarned) + claim.Reward = claim.Reward.Add(newRewardsCoin) + } + } + return claim +} diff --git a/x/incentive/keeper/rewards_delegator_init_test.go b/x/incentive/keeper/rewards_delegator_init_test.go index 255adadd..9f006178 100644 --- a/x/incentive/keeper/rewards_delegator_init_test.go +++ b/x/incentive/keeper/rewards_delegator_init_test.go @@ -10,7 +10,7 @@ import ( "github.com/kava-labs/kava/x/incentive/types" ) -// InitializeHardDelegatorRewardTests runs unit tests for the keeper.InitializeHardDelegatorReward method +// InitializeDelegatorRewardTests runs unit tests for the keeper.InitializeDelegatorReward method // // inputs // - claim in store if it exists (only claim.DelegatorRewardIndexes) @@ -19,27 +19,33 @@ import ( // // outputs // - sets or creates a claim -type InitializeHardDelegatorRewardTests struct { +type InitializeDelegatorRewardTests struct { unitTester } -func TestInitializeHardDelegatorReward(t *testing.T) { - suite.Run(t, new(InitializeHardDelegatorRewardTests)) +func TestInitializeDelegatorReward(t *testing.T) { + suite.Run(t, new(InitializeDelegatorRewardTests)) } -func (suite *InitializeHardDelegatorRewardTests) TestClaimIndexesAreSetWhenClaimDoesNotExist() { +// Hardcoded to use bond denom +func (suite *InitializeDelegatorRewardTests) storeGlobalDelegatorFactor(multiRewardIndexes types.MultiRewardIndexes) { + multiRewardIndex, _ := multiRewardIndexes.GetRewardIndex(types.BondDenom) + suite.keeper.SetDelegatorRewardIndexes(suite.ctx, types.BondDenom, multiRewardIndex.RewardIndexes) +} + +func (suite *InitializeDelegatorRewardTests) TestClaimIndexesAreSetWhenClaimDoesNotExist() { globalIndex := arbitraryDelegatorRewardIndexes suite.storeGlobalDelegatorIndexes(globalIndex) delegator := arbitraryAddress() - suite.keeper.InitializeHardDelegatorReward(suite.ctx, delegator) + suite.keeper.InitializeDelegatorReward(suite.ctx, delegator) - syncedClaim, f := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, delegator) + syncedClaim, f := suite.keeper.GetDelegatorClaim(suite.ctx, delegator) suite.True(f) - suite.Equal(globalIndex, syncedClaim.DelegatorRewardIndexes) + suite.Equal(globalIndex, syncedClaim.RewardIndexes) } -func (suite *InitializeHardDelegatorRewardTests) TestClaimIsSyncedAndIndexesAreSetWhenClaimDoesExist() { +func (suite *InitializeDelegatorRewardTests) TestClaimIsSyncedAndIndexesAreSetWhenClaimDoesExist() { validatorAddress := arbitraryValidatorAddress() sk := fakeStakingKeeper{ delegations: stakingtypes.Delegations{{ @@ -55,28 +61,28 @@ func (suite *InitializeHardDelegatorRewardTests) TestClaimIsSyncedAndIndexesAreS } suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, sk, nil) - claim := types.HardLiquidityProviderClaim{ + claim := types.DelegatorClaim{ BaseMultiClaim: types.BaseMultiClaim{ Owner: arbitraryAddress(), }, - DelegatorRewardIndexes: arbitraryDelegatorRewardIndexes, + RewardIndexes: arbitraryDelegatorRewardIndexes, } - suite.storeClaim(claim) + suite.storeDelegatorClaim(claim) // Set the global factor to a value different to one in claim so // we can detect if it is overwritten. - rewardIndexes, _ := claim.DelegatorRewardIndexes.Get(types.BondDenom) + rewardIndexes, _ := claim.RewardIndexes.Get(types.BondDenom) globalIndexes := increaseRewardFactors(rewardIndexes) // Update the claim object with the new global factor - bondIndex, _ := claim.DelegatorRewardIndexes.GetRewardIndexIndex(types.BondDenom) - claim.DelegatorRewardIndexes[bondIndex].RewardIndexes = globalIndexes - suite.storeGlobalDelegatorIndexes(claim.DelegatorRewardIndexes) + bondIndex, _ := claim.RewardIndexes.GetRewardIndexIndex(types.BondDenom) + claim.RewardIndexes[bondIndex].RewardIndexes = globalIndexes + suite.storeGlobalDelegatorFactor(claim.RewardIndexes) - suite.keeper.InitializeHardDelegatorReward(suite.ctx, claim.Owner) + suite.keeper.InitializeDelegatorReward(suite.ctx, claim.Owner) - syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner) - suite.Equal(globalIndexes, syncedClaim.DelegatorRewardIndexes[bondIndex].RewardIndexes) + syncedClaim, _ := suite.keeper.GetDelegatorClaim(suite.ctx, claim.Owner) + suite.Equal(globalIndexes, syncedClaim.RewardIndexes[bondIndex].RewardIndexes) suite.Truef(syncedClaim.Reward.IsAllGT(claim.Reward), "'%s' not greater than '%s'", syncedClaim.Reward, claim.Reward) } diff --git a/x/incentive/keeper/rewards_delegator_sync_test.go b/x/incentive/keeper/rewards_delegator_sync_test.go index 9ab0b4a4..d35d780a 100644 --- a/x/incentive/keeper/rewards_delegator_sync_test.go +++ b/x/incentive/keeper/rewards_delegator_sync_test.go @@ -10,7 +10,7 @@ import ( "github.com/kava-labs/kava/x/incentive/types" ) -// SynchronizeHardDelegatorRewardTests runs unit tests for the keeper.SynchronizeHardDelegatorReward method +// SynchronizeDelegatorRewardTests runs unit tests for the keeper.SynchronizeDelegatorReward method // // inputs // - claim in store if it exists (only claim.DelegatorRewardIndexes and claim.Reward) @@ -20,64 +20,69 @@ import ( // // outputs // - sets or creates a claim -type SynchronizeHardDelegatorRewardTests struct { +type SynchronizeDelegatorRewardTests struct { unitTester } -func TestSynchronizeHardDelegatorReward(t *testing.T) { - suite.Run(t, new(SynchronizeHardDelegatorRewardTests)) +func TestSynchronizeDelegatorReward(t *testing.T) { + suite.Run(t, new(SynchronizeDelegatorRewardTests)) } -func (suite *SynchronizeHardDelegatorRewardTests) TestClaimIndexesAreUnchangedWhenGlobalFactorUnchanged() { +func (suite *SynchronizeDelegatorRewardTests) storeGlobalDelegatorFactor(multiRewardIndexes types.MultiRewardIndexes) { + multiRewardIndex, _ := multiRewardIndexes.GetRewardIndex(types.BondDenom) + suite.keeper.SetDelegatorRewardIndexes(suite.ctx, types.BondDenom, multiRewardIndex.RewardIndexes) +} + +func (suite *SynchronizeDelegatorRewardTests) TestClaimIndexesAreUnchangedWhenGlobalFactorUnchanged() { delegator := arbitraryAddress() stakingKeeper := fakeStakingKeeper{} // use an empty staking keeper that returns no delegations suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil) - claim := types.HardLiquidityProviderClaim{ + claim := types.DelegatorClaim{ BaseMultiClaim: types.BaseMultiClaim{ Owner: delegator, }, - DelegatorRewardIndexes: arbitraryDelegatorRewardIndexes, + RewardIndexes: arbitraryDelegatorRewardIndexes, } - suite.storeClaim(claim) + suite.storeDelegatorClaim(claim) - suite.storeGlobalDelegatorIndexes(claim.DelegatorRewardIndexes) + suite.storeGlobalDelegatorFactor(claim.RewardIndexes) - suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, claim.Owner, nil, false) + suite.keeper.SynchronizeDelegatorRewards(suite.ctx, claim.Owner, nil, false) - syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner) - suite.Equal(claim.DelegatorRewardIndexes, syncedClaim.DelegatorRewardIndexes) + syncedClaim, _ := suite.keeper.GetDelegatorClaim(suite.ctx, claim.Owner) + suite.Equal(claim.RewardIndexes, syncedClaim.RewardIndexes) } -func (suite *SynchronizeHardDelegatorRewardTests) TestClaimIndexesAreUpdatedWhenGlobalFactorIncreased() { +func (suite *SynchronizeDelegatorRewardTests) TestClaimIndexesAreUpdatedWhenGlobalFactorIncreased() { delegator := arbitraryAddress() suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, fakeStakingKeeper{}, nil) - claim := types.HardLiquidityProviderClaim{ + claim := types.DelegatorClaim{ BaseMultiClaim: types.BaseMultiClaim{ Owner: delegator, }, - DelegatorRewardIndexes: arbitraryDelegatorRewardIndexes, + RewardIndexes: arbitraryDelegatorRewardIndexes, } - suite.storeClaim(claim) + suite.storeDelegatorClaim(claim) - rewardIndexes, _ := claim.DelegatorRewardIndexes.Get(types.BondDenom) + rewardIndexes, _ := claim.RewardIndexes.Get(types.BondDenom) globalIndexes := increaseRewardFactors(rewardIndexes) // Update the claim object with the new global factor - bondIndex, _ := claim.DelegatorRewardIndexes.GetRewardIndexIndex(types.BondDenom) - claim.DelegatorRewardIndexes[bondIndex].RewardIndexes = globalIndexes - suite.storeGlobalDelegatorIndexes(claim.DelegatorRewardIndexes) + bondIndex, _ := claim.RewardIndexes.GetRewardIndexIndex(types.BondDenom) + claim.RewardIndexes[bondIndex].RewardIndexes = globalIndexes + suite.storeGlobalDelegatorFactor(claim.RewardIndexes) - suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, claim.Owner, nil, false) + suite.keeper.SynchronizeDelegatorRewards(suite.ctx, claim.Owner, nil, false) - syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner) - suite.Equal(globalIndexes, syncedClaim.DelegatorRewardIndexes[bondIndex].RewardIndexes) + syncedClaim, _ := suite.keeper.GetDelegatorClaim(suite.ctx, claim.Owner) + suite.Equal(globalIndexes, syncedClaim.RewardIndexes[bondIndex].RewardIndexes) } -func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsUnchangedWhenGlobalFactorUnchanged() { +func (suite *SynchronizeDelegatorRewardTests) TestRewardIsUnchangedWhenGlobalFactorUnchanged() { delegator := arbitraryAddress() validatorAddress := arbitraryValidatorAddress() stakingKeeper := fakeStakingKeeper{ @@ -94,12 +99,12 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsUnchangedWhenGloba } suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil) - claim := types.HardLiquidityProviderClaim{ + claim := types.DelegatorClaim{ BaseMultiClaim: types.BaseMultiClaim{ Owner: delegator, Reward: arbitraryCoins(), }, - DelegatorRewardIndexes: types.MultiRewardIndexes{{ + RewardIndexes: types.MultiRewardIndexes{{ CollateralType: types.BondDenom, RewardIndexes: types.RewardIndexes{ { @@ -111,18 +116,18 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsUnchangedWhenGloba }, }}, } - suite.storeClaim(claim) + suite.storeDelegatorClaim(claim) - suite.storeGlobalDelegatorIndexes(claim.DelegatorRewardIndexes) + suite.storeGlobalDelegatorFactor(claim.RewardIndexes) - suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, claim.Owner, nil, false) + suite.keeper.SynchronizeDelegatorRewards(suite.ctx, claim.Owner, nil, false) - syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner) + syncedClaim, _ := suite.keeper.GetDelegatorClaim(suite.ctx, claim.Owner) suite.Equal(claim.Reward, syncedClaim.Reward) } -func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRewardAdded() { +func (suite *SynchronizeDelegatorRewardTests) TestRewardIsIncreasedWhenNewRewardAdded() { delegator := arbitraryAddress() validatorAddress := arbitraryValidatorAddress() stakingKeeper := fakeStakingKeeper{ @@ -139,14 +144,14 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRe } suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil) - claim := types.HardLiquidityProviderClaim{ + claim := types.DelegatorClaim{ BaseMultiClaim: types.BaseMultiClaim{ Owner: delegator, Reward: arbitraryCoins(), }, - DelegatorRewardIndexes: types.MultiRewardIndexes{}, + RewardIndexes: types.MultiRewardIndexes{}, } - suite.storeClaim(claim) + suite.storeDelegatorClaim(claim) newGlobalIndexes := types.MultiRewardIndexes{{ CollateralType: types.BondDenom, @@ -161,11 +166,11 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRe }} suite.storeGlobalDelegatorIndexes(newGlobalIndexes) - suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, claim.Owner, nil, false) + suite.keeper.SynchronizeDelegatorRewards(suite.ctx, claim.Owner, nil, false) - syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner) + syncedClaim, _ := suite.keeper.GetDelegatorClaim(suite.ctx, claim.Owner) - suite.Equal(newGlobalIndexes, syncedClaim.DelegatorRewardIndexes) + suite.Equal(newGlobalIndexes, syncedClaim.RewardIndexes) suite.Equal( cs( c(types.HardLiquidityRewardDenom, 100), @@ -175,7 +180,7 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRe ) } -func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGlobalFactorIncreased() { +func (suite *SynchronizeDelegatorRewardTests) TestRewardIsIncreasedWhenGlobalFactorIncreased() { delegator := arbitraryAddress() validatorAddress := arbitraryValidatorAddress() stakingKeeper := fakeStakingKeeper{ @@ -192,12 +197,12 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGloba } suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil) - claim := types.HardLiquidityProviderClaim{ + claim := types.DelegatorClaim{ BaseMultiClaim: types.BaseMultiClaim{ Owner: delegator, Reward: arbitraryCoins(), }, - DelegatorRewardIndexes: types.MultiRewardIndexes{{ + RewardIndexes: types.MultiRewardIndexes{{ CollateralType: types.BondDenom, RewardIndexes: types.RewardIndexes{ { @@ -209,7 +214,7 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGloba }, }}, } - suite.storeClaim(claim) + suite.storeDelegatorClaim(claim) suite.storeGlobalDelegatorIndexes( types.MultiRewardIndexes{ @@ -227,9 +232,9 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGloba }, ) - suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, claim.Owner, nil, false) + suite.keeper.SynchronizeDelegatorRewards(suite.ctx, claim.Owner, nil, false) - syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner) + syncedClaim, _ := suite.keeper.GetDelegatorClaim(suite.ctx, claim.Owner) suite.Equal( cs( @@ -263,7 +268,7 @@ func unslashedNotBondedValidator(address sdk.ValAddress) stakingtypes.Validator } } -func (suite *SynchronizeHardDelegatorRewardTests) TestGetDelegatedWhenValAddrIsNil() { +func (suite *SynchronizeDelegatorRewardTests) TestGetDelegatedWhenValAddrIsNil() { // when valAddr is nil, get total delegated to bonded validators delegator := arbitraryAddress() validatorAddresses := generateValidatorAddresses(4) @@ -306,7 +311,7 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestGetDelegatedWhenValAddrIsN suite.keeper.GetTotalDelegated(suite.ctx, delegator, nil, false), ) } -func (suite *SynchronizeHardDelegatorRewardTests) TestGetDelegatedWhenExcludingAValidator() { +func (suite *SynchronizeDelegatorRewardTests) TestGetDelegatedWhenExcludingAValidator() { // when valAddr is x, get total delegated to bonded validators excluding those to x delegator := arbitraryAddress() validatorAddresses := generateValidatorAddresses(4) @@ -349,7 +354,7 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestGetDelegatedWhenExcludingA suite.keeper.GetTotalDelegated(suite.ctx, delegator, validatorAddresses[0], false), ) } -func (suite *SynchronizeHardDelegatorRewardTests) TestGetDelegatedWhenIncludingAValidator() { +func (suite *SynchronizeDelegatorRewardTests) TestGetDelegatedWhenIncludingAValidator() { // when valAddr is x, get total delegated to bonded validators including those to x delegator := arbitraryAddress() validatorAddresses := generateValidatorAddresses(4) diff --git a/x/incentive/keeper/rewards_delegator_test.go b/x/incentive/keeper/rewards_delegator_test.go index fad10edd..a4d577ba 100644 --- a/x/incentive/keeper/rewards_delegator_test.go +++ b/x/incentive/keeper/rewards_delegator_test.go @@ -64,7 +64,7 @@ func (suite *DelegatorRewardsTestSuite) SetupWithGenState(authBuilder app.AuthGe ) } -func (suite *DelegatorRewardsTestSuite) TestAccumulateHardDelegatorRewards() { +func (suite *DelegatorRewardsTestSuite) TestAccumulateDelegatorRewards() { type args struct { delegation sdk.Coin rewardsPerSecond sdk.Coins @@ -145,18 +145,18 @@ func (suite *DelegatorRewardsTestSuite) TestAccumulateHardDelegatorRewards() { runAtTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * tc.args.timeElapsed)) runCtx := suite.ctx.WithBlockTime(runAtTime) - rewardPeriods, found := suite.keeper.GetHardDelegatorRewardPeriods(runCtx, tc.args.delegation.Denom) + rewardPeriods, found := suite.keeper.GetDelegatorRewardPeriods(runCtx, tc.args.delegation.Denom) suite.Require().True(found) - err = suite.keeper.AccumulateHardDelegatorRewards(runCtx, rewardPeriods) + err = suite.keeper.AccumulateDelegatorRewards(runCtx, rewardPeriods) suite.Require().NoError(err) - rewardIndexes, _ := suite.keeper.GetHardDelegatorRewardIndexes(runCtx, tc.args.delegation.Denom) + rewardIndexes, _ := suite.keeper.GetDelegatorRewardIndexes(runCtx, tc.args.delegation.Denom) suite.Require().Equal(tc.args.expectedRewardIndexes, rewardIndexes) }) } } -func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() { +func (suite *DelegatorRewardsTestSuite) TestSynchronizeDelegatorReward() { type args struct { delegation sdk.Coin rewardsPerSecond sdk.Coins @@ -249,10 +249,10 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() { suite.Require().Equal(valAcc.Status, sdk.Bonded) suite.Require().Equal(valAcc.Tokens, tc.args.delegation.Amount.Add(selfDelegationCoins.Amount)) - // Check that Staking hooks initialized a HardLiquidityProviderClaim - claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + // Check that Staking hooks initialized a DelegatorClaim + claim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) - for _, rewardIndex := range claim.DelegatorRewardIndexes[0].RewardIndexes { + for _, rewardIndex := range claim.RewardIndexes[0].RewardIndexes { suite.Require().Equal(sdk.ZeroDec(), rewardIndex.RewardFactor) } @@ -265,10 +265,10 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() { previousBlockTime = updatedBlockTime blockCtx := suite.ctx.WithBlockTime(updatedBlockTime) - rewardPeriods, found := suite.keeper.GetHardDelegatorRewardPeriods(blockCtx, tc.args.delegation.Denom) + rewardPeriods, found := suite.keeper.GetDelegatorRewardPeriods(blockCtx, tc.args.delegation.Denom) suite.Require().True(found) - err := suite.keeper.AccumulateHardDelegatorRewards(blockCtx, rewardPeriods) + err := suite.keeper.AccumulateDelegatorRewards(blockCtx, rewardPeriods) suite.Require().NoError(err) } updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed)) @@ -276,19 +276,19 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() { // After we've accumulated, run synchronize suite.Require().NotPanics(func() { - suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, suite.addrs[0], nil, false) + suite.keeper.SynchronizeDelegatorRewards(suite.ctx, suite.addrs[0], nil, false) }) // Check that reward factor and claim have been updated as expected - rewardIndexes, _ := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, tc.args.delegation.Denom) + rewardIndexes, _ := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, tc.args.delegation.Denom) for i, rewardPerSecond := range tc.args.rewardsPerSecond { rewardFactor, _ := rewardIndexes.Get(rewardPerSecond.Denom) suite.Require().Equal(tc.args.expectedRewardIndexes[i].RewardFactor, rewardFactor) } - claim, found = suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + claim, found = suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) - for i, delegatorRewardIndex := range claim.DelegatorRewardIndexes[0].RewardIndexes { + for i, delegatorRewardIndex := range claim.RewardIndexes[0].RewardIndexes { suite.Require().Equal(tc.args.expectedRewardIndexes[i].RewardFactor, delegatorRewardIndex.RewardFactor) } suite.Require().Equal(tc.args.expectedRewards, claim.Reward) @@ -296,7 +296,7 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() { } } -func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchronization() { +func (suite *DelegatorRewardsTestSuite) TestSimulateDelegatorRewardSynchronization() { type args struct { delegation sdk.Coin rewardsPerSecond sdk.Coins @@ -365,10 +365,10 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni staking.EndBlocker(suite.ctx, suite.stakingKeeper) - // Check that Staking hooks initialized a HardLiquidityProviderClaim - claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + // Check that Staking hooks initialized a DelegatorClaim + claim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) - for _, rewardIndex := range claim.DelegatorRewardIndexes[0].RewardIndexes { + for _, rewardIndex := range claim.RewardIndexes[0].RewardIndexes { suite.Require().Equal(sdk.ZeroDec(), rewardIndex.RewardFactor) } @@ -381,21 +381,21 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni previousBlockTime = updatedBlockTime blockCtx := suite.ctx.WithBlockTime(updatedBlockTime) - // Accumulate hard delegator rewards - rewardPeriods, found := suite.keeper.GetHardDelegatorRewardPeriods(blockCtx, tc.args.delegation.Denom) + // Accumulate delegator rewards + rewardPeriods, found := suite.keeper.GetDelegatorRewardPeriods(blockCtx, tc.args.delegation.Denom) suite.Require().True(found) - err := suite.keeper.AccumulateHardDelegatorRewards(blockCtx, rewardPeriods) + err := suite.keeper.AccumulateDelegatorRewards(blockCtx, rewardPeriods) suite.Require().NoError(err) } updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed)) suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime) // Check that the synced claim held in memory has properly simulated syncing - syncedClaim := suite.keeper.SimulateHardSynchronization(suite.ctx, claim) + syncedClaim := suite.keeper.SimulateDelegatorSynchronization(suite.ctx, claim) for i, expectedRewardIndex := range tc.args.expectedRewardIndexes { // Check that the user's claim's reward index matches the expected reward index - multiRewardIndex, found := syncedClaim.DelegatorRewardIndexes.Get(types.BondDenom) + multiRewardIndex, found := syncedClaim.RewardIndexes.Get(types.BondDenom) suite.Require().True(found) suite.Require().Equal(expectedRewardIndex, multiRewardIndex[i]) @@ -503,14 +503,14 @@ func (suite *DelegatorRewardsTestSuite) TestUnbondingValidatorSyncsClaim() { // but don't start the next block as it will accumulate delegator rewards and we won't be able to tell if the user's reward was synced. // Check that the user's claim has been synced. ie rewards added, index updated - claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + claim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) - rewardIndexes, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) + rewardIndexes, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom) suite.Require().True(found) globalIndex, found := rewardIndexes.Get(rewardsPerSecond[0].Denom) suite.Require().True(found) - claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) + claimIndex, found := claim.RewardIndexes.GetRewardIndex(bondDenom) suite.Require().True(found) suite.Require().Equal(globalIndex, claimIndex.RewardIndexes[0].RewardFactor) @@ -523,17 +523,17 @@ func (suite *DelegatorRewardsTestSuite) TestUnbondingValidatorSyncsClaim() { suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(3 * blockDuration)) _ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) - suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, suite.addrs[0], nil, false) + suite.keeper.SynchronizeDelegatorRewards(suite.ctx, suite.addrs[0], nil, false) // rewards are the same as before - laterClaim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + laterClaim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) suite.Require().Equal(claim.Reward, laterClaim.Reward) // claim index has been updated to latest global value - laterClaimIndex, found := laterClaim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) + laterClaimIndex, found := laterClaim.RewardIndexes.GetRewardIndex(bondDenom) suite.Require().True(found) - rewardIndexes, found = suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) + rewardIndexes, found = suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom) suite.Require().True(found) globalIndex, found = rewardIndexes.Get(rewardsPerSecond[0].Denom) suite.Require().True(found) @@ -597,14 +597,14 @@ func (suite *DelegatorRewardsTestSuite) TestBondingValidatorSyncsClaim() { // but don't start the next block as it will accumulate delegator rewards and we won't be able to tell if the user's reward was synced. // Check that the user's claim has been synced. ie rewards added, index updated - claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + claim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) - rewardIndexes, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) + rewardIndexes, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom) suite.Require().True(found) globalIndex, found := rewardIndexes.Get(rewardsPerSecond[0].Denom) suite.Require().True(found) - claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) + claimIndex, found := claim.RewardIndexes.GetRewardIndex(bondDenom) suite.Require().True(found) suite.Require().Equal(globalIndex, claimIndex.RewardIndexes[0].RewardFactor) @@ -617,17 +617,17 @@ func (suite *DelegatorRewardsTestSuite) TestBondingValidatorSyncsClaim() { suite.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(3 * blockDuration)) _ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) - suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, suite.addrs[0], nil, false) + suite.keeper.SynchronizeDelegatorRewards(suite.ctx, suite.addrs[0], nil, false) // rewards are greater than before - laterClaim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + laterClaim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) suite.Require().True(laterClaim.Reward.IsAllGT(claim.Reward)) // claim index has been updated to latest global value - laterClaimIndex, found := laterClaim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) + laterClaimIndex, found := laterClaim.RewardIndexes.GetRewardIndex(bondDenom) suite.Require().True(found) - rewardIndexes, found = suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) + rewardIndexes, found = suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom) suite.Require().True(found) globalIndex, found = rewardIndexes.Get(rewardsPerSecond[0].Denom) suite.Require().True(found) @@ -674,11 +674,11 @@ func (suite *DelegatorRewardsTestSuite) TestSlashingValidatorSyncsClaim() { suite.Require().NoError(err) // Check that claim has been created with synced reward index but no reward coins - initialClaim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + initialClaim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.True(found) - initialGlobalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) + initialGlobalIndex, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom) suite.True(found) - initialClaimIndex, found := initialClaim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) + initialClaimIndex, found := initialClaim.RewardIndexes.GetRewardIndex(bondDenom) suite.True(found) suite.Require().Equal(initialGlobalIndex, initialClaimIndex.RewardIndexes) suite.True(initialClaim.Reward.Empty()) // Initial claim should not have any rewards @@ -697,11 +697,11 @@ func (suite *DelegatorRewardsTestSuite) TestSlashingValidatorSyncsClaim() { stakingKeeper.Slash(suite.ctx, validator.ConsAddress(), suite.ctx.BlockHeight(), 10, fraction) // Check that the user's claim has been synced. ie rewards added, index updated - claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + claim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) - globalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) + globalIndex, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom) suite.Require().True(found) - claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) + claimIndex, found := claim.RewardIndexes.GetRewardIndex(bondDenom) suite.Require().True(found) suite.Require().Equal(globalIndex, claimIndex.RewardIndexes) @@ -754,12 +754,12 @@ func (suite *DelegatorRewardsTestSuite) TestRedelegationSyncsClaim() { suite.Require().NoError(err) // Check that the user's claim has been synced. ie rewards added, index updated - claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) + claim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0]) suite.Require().True(found) - globalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) + globalIndex, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom) suite.Require().True(found) - claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) + claimIndex, found := claim.RewardIndexes.GetRewardIndex(bondDenom) suite.Require().True(found) suite.Require().Equal(globalIndex, claimIndex.RewardIndexes) suite.Require().Equal( diff --git a/x/incentive/keeper/rewards_supply.go b/x/incentive/keeper/rewards_supply.go index 28f8ea6d..cfc33584 100644 --- a/x/incentive/keeper/rewards_supply.go +++ b/x/incentive/keeper/rewards_supply.go @@ -82,7 +82,7 @@ func (k Keeper) AccumulateHardSupplyRewards(ctx sdk.Context, rewardPeriod types. func (k Keeper) InitializeHardSupplyReward(ctx sdk.Context, deposit hardtypes.Deposit) { claim, found := k.GetHardLiquidityProviderClaim(ctx, deposit.Depositor) if !found { - claim = types.NewHardLiquidityProviderClaim(deposit.Depositor, sdk.Coins{}, nil, nil, nil) + claim = types.NewHardLiquidityProviderClaim(deposit.Depositor, sdk.Coins{}, nil, nil) } var supplyRewardIndexes types.MultiRewardIndexes @@ -143,7 +143,7 @@ func (k Keeper) SynchronizeHardSupplyReward(ctx sdk.Context, deposit hardtypes.D func (k Keeper) UpdateHardSupplyIndexDenoms(ctx sdk.Context, deposit hardtypes.Deposit) { claim, found := k.GetHardLiquidityProviderClaim(ctx, deposit.Depositor) if !found { - claim = types.NewHardLiquidityProviderClaim(deposit.Depositor, sdk.Coins{}, nil, nil, nil) + claim = types.NewHardLiquidityProviderClaim(deposit.Depositor, sdk.Coins{}, nil, nil) } depositDenoms := getDenoms(deposit.Amount) @@ -186,9 +186,6 @@ func (k Keeper) SynchronizeHardLiquidityProviderClaim(ctx sdk.Context, owner sdk if foundBorrow { k.SynchronizeHardBorrowReward(ctx, borrow) } - - // Synchronize any hard delegator rewards - k.SynchronizeHardDelegatorRewards(ctx, owner, nil, false) } // ZeroHardLiquidityProviderClaim zeroes out the claim object's rewards and returns the updated claim object @@ -300,56 +297,6 @@ func (k Keeper) SimulateHardSynchronization(ctx sdk.Context, claim types.HardLiq } } - // 3. Simulate delegator rewards - for _, ri := range claim.DelegatorRewardIndexes { - // For each Delegator reward index (there's only one: the bond denom 'ukava') - globalRewardIndexes, foundGlobalRewardIndexes := k.GetHardDelegatorRewardIndexes(ctx, ri.CollateralType) - if !foundGlobalRewardIndexes { - continue - } - - userRewardIndexes, foundUserRewardIndexes := claim.DelegatorRewardIndexes.GetRewardIndex(ri.CollateralType) - if !foundUserRewardIndexes { - continue - } - - userRewardIndexIndex, foundUserRewardIndexIndex := claim.DelegatorRewardIndexes.GetRewardIndexIndex(ri.CollateralType) - if !foundUserRewardIndexIndex { - continue - } - - amtDelegated := k.GetTotalDelegated(ctx, claim.GetOwner(), sdk.ValAddress(claim.Owner.String()), true) - - for _, globalRewardIndex := range globalRewardIndexes { - userRewardIndex, foundUserRewardIndex := userRewardIndexes.RewardIndexes.GetRewardIndex(globalRewardIndex.CollateralType) - if !foundUserRewardIndex { - userRewardIndex = types.NewRewardIndex(globalRewardIndex.CollateralType, sdk.ZeroDec()) - userRewardIndexes.RewardIndexes = append(userRewardIndexes.RewardIndexes, userRewardIndex) - claim.DelegatorRewardIndexes[userRewardIndexIndex].RewardIndexes = append(claim.DelegatorRewardIndexes[userRewardIndexIndex].RewardIndexes, userRewardIndex) - } - - globalRewardFactor := globalRewardIndex.RewardFactor - userRewardFactor := userRewardIndex.RewardFactor - rewardsAccumulatedFactor := globalRewardFactor.Sub(userRewardFactor) - if rewardsAccumulatedFactor.IsZero() { - continue - } - - rewardsEarned := rewardsAccumulatedFactor.Mul(amtDelegated).RoundInt() - if rewardsEarned.IsZero() || rewardsEarned.IsNegative() { - continue - } - - factorIndex, foundFactorIndex := userRewardIndexes.RewardIndexes.GetFactorIndex(globalRewardIndex.CollateralType) - if !foundFactorIndex { - continue - } - claim.DelegatorRewardIndexes[userRewardIndexIndex].RewardIndexes[factorIndex].RewardFactor = globalRewardIndex.RewardFactor - newRewardsCoin := sdk.NewCoin(userRewardIndex.CollateralType, rewardsEarned) - claim.Reward = claim.Reward.Add(newRewardsCoin) - } - } - return claim } diff --git a/x/incentive/keeper/rewards_supply_init_test.go b/x/incentive/keeper/rewards_supply_init_test.go index 354e8215..0c0927d0 100644 --- a/x/incentive/keeper/rewards_supply_init_test.go +++ b/x/incentive/keeper/rewards_supply_init_test.go @@ -36,7 +36,7 @@ func (suite *InitializeHardSupplyRewardTests) TestClaimIndexesAreSetWhenClaimExi // which means UpdateHardSupplyIndexDenoms was called and should have remove indexes. SupplyRewardIndexes: types.MultiRewardIndexes{}, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := nonEmptyMultiRewardIndexes suite.storeGlobalSupplyIndexes(globalIndexes) diff --git a/x/incentive/keeper/rewards_supply_sync_test.go b/x/incentive/keeper/rewards_supply_sync_test.go index e69055a7..7f12f3d4 100644 --- a/x/incentive/keeper/rewards_supply_sync_test.go +++ b/x/incentive/keeper/rewards_supply_sync_test.go @@ -35,7 +35,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestClaimIndexesAreUpdatedWhenGlo }, SupplyRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := increaseAllRewardFactors(nonEmptyMultiRewardIndexes) suite.storeGlobalSupplyIndexes(globalIndexes) @@ -60,7 +60,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestClaimIndexesAreUnchangedWhenG }, SupplyRewardIndexes: unchangingIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) suite.storeGlobalSupplyIndexes(unchangingIndexes) @@ -84,7 +84,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestClaimIndexesAreUpdatedWhenNew }, SupplyRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := appendUniqueMultiRewardIndex(nonEmptyMultiRewardIndexes) suite.storeGlobalSupplyIndexes(globalIndexes) @@ -110,7 +110,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestClaimIndexesAreUpdatedWhenNew }, SupplyRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := appendUniqueRewardIndexToFirstItem(nonEmptyMultiRewardIndexes) suite.storeGlobalSupplyIndexes(globalIndexes) @@ -151,7 +151,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestRewardIsIncrementedWhenGlobal }, }, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) suite.storeGlobalSupplyIndexes(types.MultiRewardIndexes{ { @@ -202,7 +202,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestRewardIsIncrementedWhenNewRew }, }, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := types.MultiRewardIndexes{ { @@ -265,7 +265,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestRewardIsIncrementedWhenNewRew }, }, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := types.MultiRewardIndexes{ { diff --git a/x/incentive/keeper/rewards_supply_update_test.go b/x/incentive/keeper/rewards_supply_update_test.go index e7c86c25..cf32199d 100644 --- a/x/incentive/keeper/rewards_supply_update_test.go +++ b/x/incentive/keeper/rewards_supply_update_test.go @@ -33,7 +33,7 @@ func (suite *UpdateHardSupplyIndexDenomsTests) TestClaimIndexesAreRemovedForDeno }, SupplyRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) suite.storeGlobalSupplyIndexes(claim.SupplyRewardIndexes) // remove one denom from the indexes already in the deposit @@ -56,7 +56,7 @@ func (suite *UpdateHardSupplyIndexDenomsTests) TestClaimIndexesAreAddedForNewlyS }, SupplyRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) globalIndexes := appendUniqueMultiRewardIndex(claim.SupplyRewardIndexes) suite.storeGlobalSupplyIndexes(globalIndexes) @@ -78,7 +78,7 @@ func (suite *UpdateHardSupplyIndexDenomsTests) TestClaimIndexesAreUnchangedWhenS }, SupplyRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) // Set global indexes with same denoms but different values. // UpdateHardSupplyIndexDenoms should ignore the new values. suite.storeGlobalSupplyIndexes(increaseAllRewardFactors(claim.SupplyRewardIndexes)) @@ -101,7 +101,7 @@ func (suite *UpdateHardSupplyIndexDenomsTests) TestEmptyClaimIndexesAreAddedForN }, SupplyRewardIndexes: nonEmptyMultiRewardIndexes, } - suite.storeClaim(claim) + suite.storeHardClaim(claim) suite.storeGlobalSupplyIndexes(claim.SupplyRewardIndexes) // add a denom to the deposited amount that is not in the global or claim's indexes diff --git a/x/incentive/keeper/unit_test.go b/x/incentive/keeper/unit_test.go index 2fcd8828..0a6d7e06 100644 --- a/x/incentive/keeper/unit_test.go +++ b/x/incentive/keeper/unit_test.go @@ -76,7 +76,7 @@ func (suite *unitTester) storeGlobalSupplyIndexes(indexes types.MultiRewardIndex func (suite *unitTester) storeGlobalDelegatorIndexes(multiRewardIndexes types.MultiRewardIndexes) { // Hardcoded to use bond denom multiRewardIndex, _ := multiRewardIndexes.GetRewardIndex(types.BondDenom) - suite.keeper.SetHardDelegatorRewardIndexes(suite.ctx, types.BondDenom, multiRewardIndex.RewardIndexes) + suite.keeper.SetDelegatorRewardIndexes(suite.ctx, types.BondDenom, multiRewardIndex.RewardIndexes) } func (suite *unitTester) storeGlobalSwapIndexes(indexes types.MultiRewardIndexes) { for _, i := range indexes { @@ -84,10 +84,14 @@ func (suite *unitTester) storeGlobalSwapIndexes(indexes types.MultiRewardIndexes } } -func (suite *unitTester) storeClaim(claim types.HardLiquidityProviderClaim) { +func (suite *unitTester) storeHardClaim(claim types.HardLiquidityProviderClaim) { suite.keeper.SetHardLiquidityProviderClaim(suite.ctx, claim) } +func (suite *unitTester) storeDelegatorClaim(claim types.DelegatorClaim) { + suite.keeper.SetDelegatorClaim(suite.ctx, claim) +} + type fakeParamSubspace struct { params types.Params } diff --git a/x/incentive/types/claims.go b/x/incentive/types/claims.go index 7a26a0dc..d73146df 100644 --- a/x/incentive/types/claims.go +++ b/x/incentive/types/claims.go @@ -11,6 +11,7 @@ import ( const ( USDXMintingClaimType = "usdx_minting" HardLiquidityProviderClaimType = "hard_liquidity_provider" + DelegatorClaimType = "delegator_claim" BondDenom = "ukava" ) @@ -163,23 +164,21 @@ func (cs USDXMintingClaims) Validate() error { // HardLiquidityProviderClaim stores the hard liquidity provider rewards that can be claimed by owner type HardLiquidityProviderClaim struct { - BaseMultiClaim `json:"base_claim" yaml:"base_claim"` - SupplyRewardIndexes MultiRewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"` - BorrowRewardIndexes MultiRewardIndexes `json:"borrow_reward_indexes" yaml:"borrow_reward_indexes"` - DelegatorRewardIndexes MultiRewardIndexes `json:"delegator_reward_indexes" yaml:"delegator_reward_indexes"` + BaseMultiClaim `json:"base_claim" yaml:"base_claim"` + SupplyRewardIndexes MultiRewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"` + BorrowRewardIndexes MultiRewardIndexes `json:"borrow_reward_indexes" yaml:"borrow_reward_indexes"` } // NewHardLiquidityProviderClaim returns a new HardLiquidityProviderClaim -func NewHardLiquidityProviderClaim(owner sdk.AccAddress, rewards sdk.Coins, supplyRewardIndexes, - borrowRewardIndexes, delegatorRewardIndexes MultiRewardIndexes) HardLiquidityProviderClaim { +func NewHardLiquidityProviderClaim(owner sdk.AccAddress, rewards sdk.Coins, + supplyRewardIndexes, borrowRewardIndexes MultiRewardIndexes) HardLiquidityProviderClaim { return HardLiquidityProviderClaim{ BaseMultiClaim: BaseMultiClaim{ Owner: owner, Reward: rewards, }, - SupplyRewardIndexes: supplyRewardIndexes, - BorrowRewardIndexes: borrowRewardIndexes, - DelegatorRewardIndexes: delegatorRewardIndexes, + SupplyRewardIndexes: supplyRewardIndexes, + BorrowRewardIndexes: borrowRewardIndexes, } } @@ -202,10 +201,6 @@ func (c HardLiquidityProviderClaim) Validate() error { return err } - if err := c.DelegatorRewardIndexes.Validate(); err != nil { - return err - } - return c.BaseMultiClaim.Validate() } @@ -214,8 +209,7 @@ func (c HardLiquidityProviderClaim) String() string { return fmt.Sprintf(`%s Supply Reward Indexes: %s, Borrow Reward Indexes: %s, - Delegator Reward Indexes: %s, - `, c.BaseMultiClaim, c.SupplyRewardIndexes, c.BorrowRewardIndexes, c.DelegatorRewardIndexes) + `, c.BaseMultiClaim, c.SupplyRewardIndexes, c.BorrowRewardIndexes) } // HasSupplyRewardIndex check if a claim has a supply reward index for the input collateral type @@ -238,9 +232,66 @@ func (c HardLiquidityProviderClaim) HasBorrowRewardIndex(denom string) (int64, b return 0, false } -// HasDelegatorRewardIndex check if a claim has a delegator reward index for the input collateral type -func (c HardLiquidityProviderClaim) HasDelegatorRewardIndex(collateralType string) (int64, bool) { - for index, ri := range c.DelegatorRewardIndexes { +// HardLiquidityProviderClaims slice of HardLiquidityProviderClaim +type HardLiquidityProviderClaims []HardLiquidityProviderClaim + +// Validate checks if all the claims are valid and there are no duplicated +// entries. +func (cs HardLiquidityProviderClaims) Validate() error { + for _, c := range cs { + if err := c.Validate(); err != nil { + return err + } + } + + return nil +} + +// DelegatorClaim stores delegation rewards that can be claimed by owner +type DelegatorClaim struct { + BaseMultiClaim `json:"base_claim" yaml:"base_claim"` + RewardIndexes MultiRewardIndexes `json:"reward_indexes" yaml:"reward_indexes"` +} + +// NewDelegatorClaim returns a new DelegatorClaim +func NewDelegatorClaim(owner sdk.AccAddress, rewards sdk.Coins, rewardIndexes MultiRewardIndexes) DelegatorClaim { + return DelegatorClaim{ + BaseMultiClaim: BaseMultiClaim{ + Owner: owner, + Reward: rewards, + }, + RewardIndexes: rewardIndexes, + } +} + +// GetType returns the claim's type +func (c DelegatorClaim) GetType() string { return DelegatorClaimType } + +// GetReward returns the claim's reward coin +func (c DelegatorClaim) GetReward() sdk.Coins { return c.Reward } + +// GetOwner returns the claim's owner +func (c DelegatorClaim) GetOwner() sdk.AccAddress { return c.Owner } + +// Validate performs a basic check of a DelegatorClaim fields +func (c DelegatorClaim) Validate() error { + if err := c.RewardIndexes.Validate(); err != nil { + return err + } + + return c.BaseMultiClaim.Validate() +} + +// String implements fmt.Stringer +func (c DelegatorClaim) String() string { + return fmt.Sprintf(`%s + Reward Indexes: %s, + `, c.BaseMultiClaim, c.RewardIndexes) +} + +// HasRewardIndex checks if a DelegatorClaim has a reward index for the input collateral type +func (c DelegatorClaim) HasRewardIndex(collateralType string) (int64, bool) { + for index, ri := range c.RewardIndexes { if ri.CollateralType == collateralType { return int64(index), true } @@ -248,12 +299,12 @@ func (c HardLiquidityProviderClaim) HasDelegatorRewardIndex(collateralType strin return 0, false } -// HardLiquidityProviderClaims slice of HardLiquidityProviderClaim -type HardLiquidityProviderClaims []HardLiquidityProviderClaim +// DelegatorClaim slice of DelegatorClaim +type DelegatorClaims []DelegatorClaim // Validate checks if all the claims are valid and there are no duplicated // entries. -func (cs HardLiquidityProviderClaims) Validate() error { +func (cs DelegatorClaims) Validate() error { for _, c := range cs { if err := c.Validate(); err != nil { return err diff --git a/x/incentive/types/codec.go b/x/incentive/types/codec.go index c1185f15..747fae6c 100644 --- a/x/incentive/types/codec.go +++ b/x/incentive/types/codec.go @@ -17,10 +17,13 @@ func RegisterCodec(cdc *codec.Codec) { cdc.RegisterInterface((*Claim)(nil), nil) cdc.RegisterConcrete(USDXMintingClaim{}, "incentive/USDXMintingClaim", nil) cdc.RegisterConcrete(HardLiquidityProviderClaim{}, "incentive/HardLiquidityProviderClaim", nil) + cdc.RegisterConcrete(DelegatorClaim{}, "incentive/DelegatorClaim", nil) // Register msgs cdc.RegisterConcrete(MsgClaimUSDXMintingReward{}, "incentive/MsgClaimUSDXMintingReward", nil) cdc.RegisterConcrete(MsgClaimHardReward{}, "incentive/MsgClaimHardReward", nil) + cdc.RegisterConcrete(MsgClaimDelegatorReward{}, "incentive/MsgClaimDelegatorReward", nil) cdc.RegisterConcrete(MsgClaimUSDXMintingRewardVVesting{}, "incentive/MsgClaimUSDXRewardVVesting", nil) cdc.RegisterConcrete(MsgClaimHardRewardVVesting{}, "incentive/MsgClaimHardRewardVVesting", nil) + cdc.RegisterConcrete(MsgClaimDelegatorRewardVVesting{}, "incentive/MsgClaimDelegatorRewardVVesting", nil) } diff --git a/x/incentive/types/genesis.go b/x/incentive/types/genesis.go index d91d8c89..8c2196ae 100644 --- a/x/incentive/types/genesis.go +++ b/x/incentive/types/genesis.go @@ -8,41 +8,45 @@ import ( // GenesisState is the state that must be provided at genesis. type GenesisState struct { - Params Params `json:"params" yaml:"params"` - USDXAccumulationTimes GenesisAccumulationTimes `json:"usdx_accumulation_times" yaml:"usdx_accumulation_times"` - HardSupplyAccumulationTimes GenesisAccumulationTimes `json:"hard_supply_accumulation_times" yaml:"hard_supply_accumulation_times"` - HardBorrowAccumulationTimes GenesisAccumulationTimes `json:"hard_borrow_accumulation_times" yaml:"hard_borrow_accumulation_times"` - HardDelegatorAccumulationTimes GenesisAccumulationTimes `json:"hard_delegator_accumulation_times" yaml:"hard_delegator_accumulation_times"` - SwapAccumulationTimes GenesisAccumulationTimes `json:"swap_accumulation_times" yaml:"swap_accumulation_times"` - USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` - HardLiquidityProviderClaims HardLiquidityProviderClaims `json:"hard_liquidity_provider_claims" yaml:"hard_liquidity_provider_claims"` + Params Params `json:"params" yaml:"params"` + USDXAccumulationTimes GenesisAccumulationTimes `json:"usdx_accumulation_times" yaml:"usdx_accumulation_times"` + HardSupplyAccumulationTimes GenesisAccumulationTimes `json:"hard_supply_accumulation_times" yaml:"hard_supply_accumulation_times"` + HardBorrowAccumulationTimes GenesisAccumulationTimes `json:"hard_borrow_accumulation_times" yaml:"hard_borrow_accumulation_times"` + DelegatorAccumulationTimes GenesisAccumulationTimes `json:"delegator_accumulation_times" yaml:"delegator_accumulation_times"` + SwapAccumulationTimes GenesisAccumulationTimes `json:"swap_accumulation_times" yaml:"swap_accumulation_times"` + USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` + HardLiquidityProviderClaims HardLiquidityProviderClaims `json:"hard_liquidity_provider_claims" yaml:"hard_liquidity_provider_claims"` + DelegatorClaims DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"` } // NewGenesisState returns a new genesis state -func NewGenesisState(params Params, usdxAccumTimes, hardSupplyAccumTimes, hardBorrowAccumTimes, hardDelegatorAccumTimes, swapAccumTimes GenesisAccumulationTimes, c USDXMintingClaims, hc HardLiquidityProviderClaims) GenesisState { +func NewGenesisState(params Params, usdxAccumTimes, hardSupplyAccumTimes, hardBorrowAccumTimes, delegatorAccumTimes, + swapAccumTimes GenesisAccumulationTimes, c USDXMintingClaims, hc HardLiquidityProviderClaims, dc DelegatorClaims) GenesisState { return GenesisState{ - Params: params, - USDXAccumulationTimes: usdxAccumTimes, - HardSupplyAccumulationTimes: hardSupplyAccumTimes, - HardBorrowAccumulationTimes: hardBorrowAccumTimes, - HardDelegatorAccumulationTimes: hardDelegatorAccumTimes, - SwapAccumulationTimes: swapAccumTimes, - USDXMintingClaims: c, - HardLiquidityProviderClaims: hc, + Params: params, + USDXAccumulationTimes: usdxAccumTimes, + HardSupplyAccumulationTimes: hardSupplyAccumTimes, + HardBorrowAccumulationTimes: hardBorrowAccumTimes, + DelegatorAccumulationTimes: delegatorAccumTimes, + SwapAccumulationTimes: swapAccumTimes, + USDXMintingClaims: c, + HardLiquidityProviderClaims: hc, + DelegatorClaims: dc, } } // DefaultGenesisState returns a default genesis state func DefaultGenesisState() GenesisState { return GenesisState{ - Params: DefaultParams(), - USDXAccumulationTimes: GenesisAccumulationTimes{}, - HardSupplyAccumulationTimes: GenesisAccumulationTimes{}, - HardBorrowAccumulationTimes: GenesisAccumulationTimes{}, - HardDelegatorAccumulationTimes: GenesisAccumulationTimes{}, - SwapAccumulationTimes: GenesisAccumulationTimes{}, - USDXMintingClaims: DefaultUSDXClaims, - HardLiquidityProviderClaims: DefaultHardClaims, + Params: DefaultParams(), + USDXAccumulationTimes: GenesisAccumulationTimes{}, + HardSupplyAccumulationTimes: GenesisAccumulationTimes{}, + HardBorrowAccumulationTimes: GenesisAccumulationTimes{}, + DelegatorAccumulationTimes: GenesisAccumulationTimes{}, + SwapAccumulationTimes: GenesisAccumulationTimes{}, + USDXMintingClaims: DefaultUSDXClaims, + HardLiquidityProviderClaims: DefaultHardClaims, + DelegatorClaims: DefaultDelegatorClaims, } } @@ -61,7 +65,7 @@ func (gs GenesisState) Validate() error { if err := gs.HardBorrowAccumulationTimes.Validate(); err != nil { return err } - if err := gs.HardDelegatorAccumulationTimes.Validate(); err != nil { + if err := gs.DelegatorAccumulationTimes.Validate(); err != nil { return err } if err := gs.SwapAccumulationTimes.Validate(); err != nil { @@ -71,7 +75,10 @@ func (gs GenesisState) Validate() error { if err := gs.HardLiquidityProviderClaims.Validate(); err != nil { return err } - return gs.USDXMintingClaims.Validate() + if err := gs.USDXMintingClaims.Validate(); err != nil { + return err + } + return gs.DelegatorClaims.Validate() } // Equal checks whether two gov GenesisState structs are equivalent diff --git a/x/incentive/types/genesis_test.go b/x/incentive/types/genesis_test.go index 0278c026..041e77d0 100644 --- a/x/incentive/types/genesis_test.go +++ b/x/incentive/types/genesis_test.go @@ -140,6 +140,7 @@ func TestGenesisStateValidate(t *testing.T) { tc.args.genAccTimes, tc.args.claims, DefaultHardClaims, + DefaultDelegatorClaims, ) err := gs.Validate() if tc.errArgs.expectPass { diff --git a/x/incentive/types/keys.go b/x/incentive/types/keys.go index 0bd02a6f..3e5c8391 100644 --- a/x/incentive/types/keys.go +++ b/x/incentive/types/keys.go @@ -23,18 +23,19 @@ const ( // Key Prefixes var ( - USDXMintingClaimKeyPrefix = []byte{0x01} // prefix for keys that store USDX minting claims - USDXMintingRewardFactorKeyPrefix = []byte{0x02} // prefix for key that stores USDX minting reward factors - PreviousUSDXMintingRewardAccrualTimeKeyPrefix = []byte{0x03} // prefix for key that stores the blocktime - HardLiquidityClaimKeyPrefix = []byte{0x04} // prefix for keys that store Hard liquidity claims - HardSupplyRewardIndexesKeyPrefix = []byte{0x05} // prefix for key that stores Hard supply reward indexes - PreviousHardSupplyRewardAccrualTimeKeyPrefix = []byte{0x06} // prefix for key that stores the previous time Hard supply rewards accrued - HardBorrowRewardIndexesKeyPrefix = []byte{0x07} // prefix for key that stores Hard borrow reward indexes - PreviousHardBorrowRewardAccrualTimeKeyPrefix = []byte{0x08} // prefix for key that stores the previous time Hard borrow rewards accrued - HardDelegatorRewardIndexesKeyPrefix = []byte{0x09} // prefix for key that stores Hard delegator reward indexes - PreviousHardDelegatorRewardAccrualTimeKeyPrefix = []byte{0x10} // prefix for key that stores the previous time Hard delegator rewards accrued - SwapRewardIndexesKeyPrefix = []byte{0x11} // prefix for key that stores swap reward indexes - PreviousSwapRewardAccrualTimeKeyPrefix = []byte{0x12} // prefix for key that stores the previous time swap rewards accrued + USDXMintingClaimKeyPrefix = []byte{0x01} // prefix for keys that store USDX minting claims + USDXMintingRewardFactorKeyPrefix = []byte{0x02} // prefix for key that stores USDX minting reward factors + PreviousUSDXMintingRewardAccrualTimeKeyPrefix = []byte{0x03} // prefix for key that stores the blocktime + HardLiquidityClaimKeyPrefix = []byte{0x04} // prefix for keys that store Hard liquidity claims + HardSupplyRewardIndexesKeyPrefix = []byte{0x05} // prefix for key that stores Hard supply reward indexes + PreviousHardSupplyRewardAccrualTimeKeyPrefix = []byte{0x06} // prefix for key that stores the previous time Hard supply rewards accrued + HardBorrowRewardIndexesKeyPrefix = []byte{0x07} // prefix for key that stores Hard borrow reward indexes + PreviousHardBorrowRewardAccrualTimeKeyPrefix = []byte{0x08} // prefix for key that stores the previous time Hard borrow rewards accrued + DelegatorClaimKeyPrefix = []byte{0x09} // prefix for keys that store delegator claims + DelegatorRewardIndexesKeyPrefix = []byte{0x10} // prefix for key that stores delegator reward indexes + PreviousDelegatorRewardAccrualTimeKeyPrefix = []byte{0x11} // prefix for key that stores the previous time delegator rewards accrued + SwapRewardIndexesKeyPrefix = []byte{0x12} // prefix for key that stores swap reward indexes + PreviousSwapRewardAccrualTimeKeyPrefix = []byte{0x13} // prefix for key that stores the previous time swap rewards accrued USDXMintingRewardDenom = "ukava" HardLiquidityRewardDenom = "hard" diff --git a/x/incentive/types/msg.go b/x/incentive/types/msg.go index fd77e7df..225bc1f9 100644 --- a/x/incentive/types/msg.go +++ b/x/incentive/types/msg.go @@ -146,7 +146,7 @@ type MsgClaimHardRewardVVesting struct { MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"` } -// NewMsgClaimHardRewardVVesting returns a new MsgClaimHardReward. +// NewMsgClaimHardRewardVVesting returns a new MsgClaimHardRewardVVesting. func NewMsgClaimHardRewardVVesting(sender, receiver sdk.AccAddress, multiplierName string) MsgClaimHardRewardVVesting { return MsgClaimHardRewardVVesting{ Sender: sender, @@ -184,3 +184,90 @@ func (msg MsgClaimHardRewardVVesting) GetSignBytes() []byte { func (msg MsgClaimHardRewardVVesting) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.Sender} } + +// MsgClaimDelegatorReward message type used to claim delegator rewards +type MsgClaimDelegatorReward struct { + Sender sdk.AccAddress `json:"sender" yaml:"sender"` + MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"` +} + +// NewMsgClaimDelegatorReward returns a new MsgClaimDelegatorReward. +func NewMsgClaimDelegatorReward(sender sdk.AccAddress, multiplierName string) MsgClaimDelegatorReward { + return MsgClaimDelegatorReward{ + Sender: sender, + MultiplierName: multiplierName, + } +} + +// Route return the message type used for routing the message. +func (msg MsgClaimDelegatorReward) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within tags. +func (msg MsgClaimDelegatorReward) Type() string { + return "claim_delegator_reward" +} + +// ValidateBasic does a simple validation check that doesn't require access to state. +func (msg MsgClaimDelegatorReward) ValidateBasic() error { + if msg.Sender.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + return MultiplierName(strings.ToLower(msg.MultiplierName)).IsValid() +} + +// GetSignBytes gets the canonical byte representation of the Msg. +func (msg MsgClaimDelegatorReward) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign. +func (msg MsgClaimDelegatorReward) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Sender} +} + +// MsgClaimDelegatorRewardVVesting message type used to claim delegator rewards for validator vesting accounts +type MsgClaimDelegatorRewardVVesting struct { + Sender sdk.AccAddress `json:"sender" yaml:"sender"` + Receiver sdk.AccAddress `json:"receiver" yaml:"receiver"` + MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"` +} + +// MsgClaimDelegatorRewardVVesting returns a new MsgClaimDelegatorRewardVVesting. +func NewMsgClaimDelegatorRewardVVesting(sender, receiver sdk.AccAddress, multiplierName string) MsgClaimDelegatorRewardVVesting { + return MsgClaimDelegatorRewardVVesting{ + Sender: sender, + Receiver: receiver, + MultiplierName: multiplierName, + } +} + +// Route return the message type used for routing the message. +func (msg MsgClaimDelegatorRewardVVesting) Route() string { return RouterKey } + +// Type returns a human-readable string for the message, intended for utilization within tags. +func (msg MsgClaimDelegatorRewardVVesting) Type() string { + return "claim_delegator_reward_vvesting" +} + +// ValidateBasic does a simple validation check that doesn't require access to state. +func (msg MsgClaimDelegatorRewardVVesting) ValidateBasic() error { + if msg.Sender.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") + } + if msg.Receiver.Empty() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be empty") + } + return MultiplierName(strings.ToLower(msg.MultiplierName)).IsValid() +} + +// GetSignBytes gets the canonical byte representation of the Msg. +func (msg MsgClaimDelegatorRewardVVesting) GetSignBytes() []byte { + bz := ModuleCdc.MustMarshalJSON(msg) + return sdk.MustSortJSON(bz) +} + +// GetSigners returns the addresses of signers that must sign. +func (msg MsgClaimDelegatorRewardVVesting) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{msg.Sender} +} diff --git a/x/incentive/types/params.go b/x/incentive/types/params.go index 7259d59d..b86248c0 100644 --- a/x/incentive/types/params.go +++ b/x/incentive/types/params.go @@ -27,7 +27,7 @@ var ( KeyUSDXMintingRewardPeriods = []byte("USDXMintingRewardPeriods") KeyHardSupplyRewardPeriods = []byte("HardSupplyRewardPeriods") KeyHardBorrowRewardPeriods = []byte("HardBorrowRewardPeriods") - KeyHardDelegatorRewardPeriods = []byte("HardDelegatorRewardPeriods") + KeyDelegatorRewardPeriods = []byte("DelegatorRewardPeriods") KeySwapRewardPeriods = []byte("SwapRewardPeriods") KeyClaimEnd = []byte("ClaimEnd") KeyMultipliers = []byte("ClaimMultipliers") @@ -37,6 +37,7 @@ var ( DefaultMultipliers = Multipliers{} DefaultUSDXClaims = USDXMintingClaims{} DefaultHardClaims = HardLiquidityProviderClaims{} + DefaultDelegatorClaims = DelegatorClaims{} DefaultGenesisAccumulationTimes = GenesisAccumulationTimes{} DefaultClaimEnd = tmtime.Canonical(time.Unix(1, 0)) GovDenom = cdptypes.DefaultGovDenom @@ -46,26 +47,26 @@ var ( // Params governance parameters for the incentive module type Params struct { - USDXMintingRewardPeriods RewardPeriods `json:"usdx_minting_reward_periods" yaml:"usdx_minting_reward_periods"` - HardSupplyRewardPeriods MultiRewardPeriods `json:"hard_supply_reward_periods" yaml:"hard_supply_reward_periods"` - HardBorrowRewardPeriods MultiRewardPeriods `json:"hard_borrow_reward_periods" yaml:"hard_borrow_reward_periods"` - HardDelegatorRewardPeriods MultiRewardPeriods `json:"hard_delegator_reward_periods" yaml:"hard_delegator_reward_periods"` - SwapRewardPeriods MultiRewardPeriods `json:"swap_reward_periods" json:"swap_reward_periods"` - ClaimMultipliers Multipliers `json:"claim_multipliers" yaml:"claim_multipliers"` - ClaimEnd time.Time `json:"claim_end" yaml:"claim_end"` + USDXMintingRewardPeriods RewardPeriods `json:"usdx_minting_reward_periods" yaml:"usdx_minting_reward_periods"` + HardSupplyRewardPeriods MultiRewardPeriods `json:"hard_supply_reward_periods" yaml:"hard_supply_reward_periods"` + HardBorrowRewardPeriods MultiRewardPeriods `json:"hard_borrow_reward_periods" yaml:"hard_borrow_reward_periods"` + DelegatorRewardPeriods MultiRewardPeriods `json:"delegator_reward_periods" yaml:"delegator_reward_periods"` + SwapRewardPeriods MultiRewardPeriods `json:"swap_reward_periods" json:"swap_reward_periods"` + ClaimMultipliers Multipliers `json:"claim_multipliers" yaml:"claim_multipliers"` + ClaimEnd time.Time `json:"claim_end" yaml:"claim_end"` } // NewParams returns a new params object -func NewParams(usdxMinting RewardPeriods, hardSupply, hardBorrow, hardDelegator, swap MultiRewardPeriods, +func NewParams(usdxMinting RewardPeriods, hardSupply, hardBorrow, delegator, swap MultiRewardPeriods, multipliers Multipliers, claimEnd time.Time) Params { return Params{ - USDXMintingRewardPeriods: usdxMinting, - HardSupplyRewardPeriods: hardSupply, - HardBorrowRewardPeriods: hardBorrow, - HardDelegatorRewardPeriods: hardDelegator, - SwapRewardPeriods: swap, - ClaimMultipliers: multipliers, - ClaimEnd: claimEnd, + USDXMintingRewardPeriods: usdxMinting, + HardSupplyRewardPeriods: hardSupply, + HardBorrowRewardPeriods: hardBorrow, + DelegatorRewardPeriods: delegator, + SwapRewardPeriods: swap, + ClaimMultipliers: multipliers, + ClaimEnd: claimEnd, } } @@ -88,12 +89,12 @@ func (p Params) String() string { USDX Minting Reward Periods: %s Hard Supply Reward Periods: %s Hard Borrow Reward Periods: %s - Hard Delegator Reward Periods: %s + Delegator Reward Periods: %s Swap Reward Periods: %s Claim Multipliers :%s Claim End Time: %s `, p.USDXMintingRewardPeriods, p.HardSupplyRewardPeriods, p.HardBorrowRewardPeriods, - p.HardDelegatorRewardPeriods, p.SwapRewardPeriods, p.ClaimMultipliers, p.ClaimEnd) + p.DelegatorRewardPeriods, p.SwapRewardPeriods, p.ClaimMultipliers, p.ClaimEnd) } // ParamKeyTable Key declaration for parameters @@ -107,7 +108,7 @@ func (p *Params) ParamSetPairs() params.ParamSetPairs { params.NewParamSetPair(KeyUSDXMintingRewardPeriods, &p.USDXMintingRewardPeriods, validateRewardPeriodsParam), params.NewParamSetPair(KeyHardSupplyRewardPeriods, &p.HardSupplyRewardPeriods, validateMultiRewardPeriodsParam), params.NewParamSetPair(KeyHardBorrowRewardPeriods, &p.HardBorrowRewardPeriods, validateMultiRewardPeriodsParam), - params.NewParamSetPair(KeyHardDelegatorRewardPeriods, &p.HardDelegatorRewardPeriods, validateMultiRewardPeriodsParam), + params.NewParamSetPair(KeyDelegatorRewardPeriods, &p.DelegatorRewardPeriods, validateMultiRewardPeriodsParam), params.NewParamSetPair(KeySwapRewardPeriods, &p.SwapRewardPeriods, validateMultiRewardPeriodsParam), params.NewParamSetPair(KeyClaimEnd, &p.ClaimEnd, validateClaimEndParam), params.NewParamSetPair(KeyMultipliers, &p.ClaimMultipliers, validateMultipliersParam), @@ -133,7 +134,7 @@ func (p Params) Validate() error { return err } - if err := validateMultiRewardPeriodsParam(p.HardDelegatorRewardPeriods); err != nil { + if err := validateMultiRewardPeriodsParam(p.DelegatorRewardPeriods); err != nil { return err } diff --git a/x/incentive/types/params_test.go b/x/incentive/types/params_test.go index 8c8ed9bb..b21b628e 100644 --- a/x/incentive/types/params_test.go +++ b/x/incentive/types/params_test.go @@ -70,11 +70,11 @@ func (suite *ParamTestSuite) TestParamValidation() { types.Large, 1, sdk.MustNewDecFromStr("1.0"), ), }, - HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, - HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, - HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, - SwapRewardPeriods: types.DefaultMultiRewardPeriods, - ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), + HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, + HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, + DelegatorRewardPeriods: types.DefaultMultiRewardPeriods, + SwapRewardPeriods: types.DefaultMultiRewardPeriods, + ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), }, errArgs{ expectPass: true, @@ -83,13 +83,13 @@ func (suite *ParamTestSuite) TestParamValidation() { { "invalid usdx minting period makes params invalid", types.Params{ - USDXMintingRewardPeriods: types.RewardPeriods{rewardPeriodWithInvalidRewardsPerSecond}, - HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, - HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, - HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, - SwapRewardPeriods: types.DefaultMultiRewardPeriods, - ClaimMultipliers: types.DefaultMultipliers, - ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), + USDXMintingRewardPeriods: types.RewardPeriods{rewardPeriodWithInvalidRewardsPerSecond}, + HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, + HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, + DelegatorRewardPeriods: types.DefaultMultiRewardPeriods, + SwapRewardPeriods: types.DefaultMultiRewardPeriods, + ClaimMultipliers: types.DefaultMultipliers, + ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), }, errArgs{ expectPass: false, @@ -99,13 +99,13 @@ func (suite *ParamTestSuite) TestParamValidation() { { "invalid hard supply periods makes params invalid", types.Params{ - USDXMintingRewardPeriods: types.DefaultRewardPeriods, - HardSupplyRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, - HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, - HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, - SwapRewardPeriods: types.DefaultMultiRewardPeriods, - ClaimMultipliers: types.DefaultMultipliers, - ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), + USDXMintingRewardPeriods: types.DefaultRewardPeriods, + HardSupplyRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, + HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, + DelegatorRewardPeriods: types.DefaultMultiRewardPeriods, + SwapRewardPeriods: types.DefaultMultiRewardPeriods, + ClaimMultipliers: types.DefaultMultipliers, + ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), }, errArgs{ expectPass: false, @@ -115,13 +115,13 @@ func (suite *ParamTestSuite) TestParamValidation() { { "invalid hard borrow periods makes params invalid", types.Params{ - USDXMintingRewardPeriods: types.DefaultRewardPeriods, - HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, - HardBorrowRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, - HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, - SwapRewardPeriods: types.DefaultMultiRewardPeriods, - ClaimMultipliers: types.DefaultMultipliers, - ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), + USDXMintingRewardPeriods: types.DefaultRewardPeriods, + HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, + HardBorrowRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, + DelegatorRewardPeriods: types.DefaultMultiRewardPeriods, + SwapRewardPeriods: types.DefaultMultiRewardPeriods, + ClaimMultipliers: types.DefaultMultipliers, + ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), }, errArgs{ expectPass: false, @@ -131,13 +131,13 @@ func (suite *ParamTestSuite) TestParamValidation() { { "invalid delegator periods makes params invalid", types.Params{ - USDXMintingRewardPeriods: types.DefaultRewardPeriods, - HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, - HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, - HardDelegatorRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, - SwapRewardPeriods: types.DefaultMultiRewardPeriods, - ClaimMultipliers: types.DefaultMultipliers, - ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), + USDXMintingRewardPeriods: types.DefaultRewardPeriods, + HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, + HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, + DelegatorRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, + SwapRewardPeriods: types.DefaultMultiRewardPeriods, + ClaimMultipliers: types.DefaultMultipliers, + ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), }, errArgs{ expectPass: false, @@ -147,13 +147,13 @@ func (suite *ParamTestSuite) TestParamValidation() { { "invalid swap periods makes params invalid", types.Params{ - USDXMintingRewardPeriods: types.DefaultRewardPeriods, - HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, - HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, - HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, - SwapRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, - ClaimMultipliers: types.DefaultMultipliers, - ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), + USDXMintingRewardPeriods: types.DefaultRewardPeriods, + HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, + HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, + DelegatorRewardPeriods: types.DefaultMultiRewardPeriods, + SwapRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, + ClaimMultipliers: types.DefaultMultipliers, + ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), }, errArgs{ expectPass: false, diff --git a/x/incentive/types/querier.go b/x/incentive/types/querier.go index 72008699..fa9f870c 100644 --- a/x/incentive/types/querier.go +++ b/x/incentive/types/querier.go @@ -11,6 +11,8 @@ const ( QueryGetHardRewardsUnsynced = "hard-rewards-unsynced" QueryGetUSDXMintingRewards = "usdx-minting-rewards" QueryGetUSDXMintingRewardsUnsynced = "usdx-minting-rewards-unsynced" + QueryGetDelegatorRewards = "delegator-rewards" + QueryGetDelegatorRewardsUnsynced = "delegator-rewards-unsynced" QueryGetRewardFactors = "reward-factors" QueryGetParams = "parameters" QueryGetRewardPeriods = "reward-periods" @@ -115,24 +117,56 @@ func NewQueryRewardFactorsParams(denom string) QueryRewardFactorsParams { } } +// QueryDelegatorRewardsParams params for query /incentive/rewards type delegator +type QueryDelegatorRewardsParams struct { + Page int `json:"page" yaml:"page"` + Limit int `json:"limit" yaml:"limit"` + Owner sdk.AccAddress +} + +// NewQueryDelegatorRewardsParams returns QueryDelegatorRewardsParams +func NewQueryDelegatorRewardsParams(page, limit int, owner sdk.AccAddress) QueryDelegatorRewardsParams { + return QueryDelegatorRewardsParams{ + Page: page, + Limit: limit, + Owner: owner, + } +} + +// QueryDelegatorRewardsUnsyncedParams params for query unsynced /incentive/rewards type delegator +type QueryDelegatorRewardsUnsyncedParams struct { + Page int `json:"page" yaml:"page"` + Limit int `json:"limit" yaml:"limit"` + Owner sdk.AccAddress +} + +// NewQueryDelegatorRewardsUnsyncedParams returns QueryDelegatorRewardsUnsyncedParams +func NewQueryDelegatorRewardsUnsyncedParams(page, limit int, owner sdk.AccAddress) QueryDelegatorRewardsUnsyncedParams { + return QueryDelegatorRewardsUnsyncedParams{ + Page: page, + Limit: limit, + Owner: owner, + } +} + // RewardFactor is a unique type returned by reward factor queries type RewardFactor struct { - Denom string `json:"denom" yaml:"denom"` - USDXMintingRewardFactor sdk.Dec `json:"usdx_minting_reward_factor" yaml:"usdx_minting_reward_factor"` - HardSupplyRewardFactors RewardIndexes `json:"hard_supply_reward_factors" yaml:"hard_supply_reward_factors"` - HardBorrowRewardFactors RewardIndexes `json:"hard_borrow_reward_factors" yaml:"hard_borrow_reward_factors"` - HardDelegatorRewardFactors RewardIndexes `json:"hard_delegator_reward_factors" yaml:"hard_delegator_reward_factors"` + Denom string `json:"denom" yaml:"denom"` + USDXMintingRewardFactor sdk.Dec `json:"usdx_minting_reward_factor" yaml:"usdx_minting_reward_factor"` + HardSupplyRewardFactors RewardIndexes `json:"hard_supply_reward_factors" yaml:"hard_supply_reward_factors"` + HardBorrowRewardFactors RewardIndexes `json:"hard_borrow_reward_factors" yaml:"hard_borrow_reward_factors"` + DelegatorRewardFactors RewardIndexes `json:"delegator_reward_factors" yaml:"delegator_reward_factors"` } // NewRewardFactor returns a new instance of RewardFactor func NewRewardFactor(denom string, usdxMintingRewardFactor sdk.Dec, hardSupplyRewardFactors, - hardBorrowRewardFactors, hardDelegatorRewardFactors RewardIndexes) RewardFactor { + hardBorrowRewardFactors, delegatorRewardFactors RewardIndexes) RewardFactor { return RewardFactor{ - Denom: denom, - USDXMintingRewardFactor: usdxMintingRewardFactor, - HardSupplyRewardFactors: hardSupplyRewardFactors, - HardBorrowRewardFactors: hardBorrowRewardFactors, - HardDelegatorRewardFactors: hardDelegatorRewardFactors, + Denom: denom, + USDXMintingRewardFactor: usdxMintingRewardFactor, + HardSupplyRewardFactors: hardSupplyRewardFactors, + HardBorrowRewardFactors: hardBorrowRewardFactors, + DelegatorRewardFactors: delegatorRewardFactors, } }