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
This commit is contained in:
Denali Marsh 2021-07-07 18:50:14 +02:00 committed by GitHub
parent c7962e45c0
commit 3fc2a63556
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1275 additions and 461 deletions

View File

@ -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,
)
}

View File

@ -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))
}

View File

@ -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)
}

View File

@ -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 (

View File

@ -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
}

View File

@ -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})
},
}
}

View File

@ -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)

View File

@ -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})
}
}

View File

@ -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)
}

View File

@ -76,6 +76,7 @@ func (suite *GenesisTestSuite) SetupTest() {
incentive.DefaultGenesisAccumulationTimes,
incentive.DefaultUSDXClaims,
incentive.DefaultHardClaims,
incentive.DefaultDelegatorClaims,
)
tApp.InitializeFromGenesisStatesWithTime(
suite.genesisTime,

View File

@ -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
}

View File

@ -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))
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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))
}

View File

@ -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
}

View File

@ -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)

View File

@ -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, &params)
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, &params)
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, &params)
@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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{
{

View File

@ -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

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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(

View File

@ -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
}

View File

@ -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)

View File

@ -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{
{

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -140,6 +140,7 @@ func TestGenesisStateValidate(t *testing.T) {
tc.args.genAccTimes,
tc.args.claims,
DefaultHardClaims,
DefaultDelegatorClaims,
)
err := gs.Validate()
if tc.errArgs.expectPass {

View File

@ -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"

View File

@ -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}
}

View File

@ -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
}

View File

@ -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,

View File

@ -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,
}
}