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) 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 hardClaims v0_15incentive.HardLiquidityProviderClaims
var delegatorClaims v0_15incentive.DelegatorClaims
for _, claim := range incentiveGS.HardLiquidityProviderClaims { for _, claim := range incentiveGS.HardLiquidityProviderClaims {
// Migrate supply multi reward indexes // Migrate supply multi reward indexes
var supplyMultiRewardIndexes v0_15incentive.MultiRewardIndexes var supplyMultiRewardIndexes v0_15incentive.MultiRewardIndexes
@ -324,7 +325,7 @@ func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisSt
borrowMultiRewardIndexes = append(borrowMultiRewardIndexes, borrowMultiRewardIndex) 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 delegatorMultiRewardIndexes v0_15incentive.MultiRewardIndexes
var delegatorRewardIndexes v0_15incentive.RewardIndexes var delegatorRewardIndexes v0_15incentive.RewardIndexes
for _, ri := range claim.DelegatorRewardIndexes { 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) delegatorMultiRewardIndex := v0_15incentive.NewMultiRewardIndex(v0_15incentive.BondDenom, delegatorRewardIndexes)
delegatorMultiRewardIndexes = append(delegatorMultiRewardIndexes, delegatorMultiRewardIndex) 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, hardClaim := v0_15incentive.NewHardLiquidityProviderClaim(claim.Owner, claim.Reward,
supplyMultiRewardIndexes, borrowMultiRewardIndexes, delegatorMultiRewardIndexes) supplyMultiRewardIndexes, borrowMultiRewardIndexes)
hardClaims = append(hardClaims, hardClaim) 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. v0_15incentive.DefaultGenesisAccumulationTimes, // There is no previous swap rewards to accumulation starts at genesis time.
usdxMintingClaims, usdxMintingClaims,
hardClaims, 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.USDXMintingClaims), len(newGenState.USDXMintingClaims))
require.Equal(t, len(oldIncentiveGenState.HardLiquidityProviderClaims), len(newGenState.HardLiquidityProviderClaims)) 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) panic(err)
} }
} }
for _, rp := range params.HardDelegatorRewardPeriods { for _, rp := range params.DelegatorRewardPeriods {
err := k.AccumulateHardDelegatorRewards(ctx, rp) err := k.AccumulateDelegatorRewards(ctx, rp)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -84,47 +84,48 @@ var (
CalculateTimeElapsed = keeper.CalculateTimeElapsed CalculateTimeElapsed = keeper.CalculateTimeElapsed
// variable aliases // variable aliases
ModuleCdc = types.ModuleCdc ModuleCdc = types.ModuleCdc
ErrClaimNotFound = types.ErrClaimNotFound ErrClaimNotFound = types.ErrClaimNotFound
ErrRewardPeriodNotFound = types.ErrRewardPeriodNotFound ErrRewardPeriodNotFound = types.ErrRewardPeriodNotFound
ErrInvalidAccountType = types.ErrInvalidAccountType ErrInvalidAccountType = types.ErrInvalidAccountType
ErrNoClaimsFound = types.ErrNoClaimsFound ErrNoClaimsFound = types.ErrNoClaimsFound
ErrInsufficientModAccountBalance = types.ErrInsufficientModAccountBalance ErrInsufficientModAccountBalance = types.ErrInsufficientModAccountBalance
ErrAccountNotFound = types.ErrAccountNotFound ErrAccountNotFound = types.ErrAccountNotFound
ErrInvalidMultiplier = types.ErrInvalidMultiplier ErrInvalidMultiplier = types.ErrInvalidMultiplier
ErrZeroClaim = types.ErrZeroClaim ErrZeroClaim = types.ErrZeroClaim
ErrClaimExpired = types.ErrClaimExpired ErrClaimExpired = types.ErrClaimExpired
ErrInvalidClaimType = types.ErrInvalidClaimType ErrInvalidClaimType = types.ErrInvalidClaimType
ErrInvalidClaimOwner = types.ErrInvalidClaimOwner ErrInvalidClaimOwner = types.ErrInvalidClaimOwner
USDXMintingClaimKeyPrefix = types.USDXMintingClaimKeyPrefix USDXMintingClaimKeyPrefix = types.USDXMintingClaimKeyPrefix
USDXMintingRewardFactorKeyPrefix = types.USDXMintingRewardFactorKeyPrefix USDXMintingRewardFactorKeyPrefix = types.USDXMintingRewardFactorKeyPrefix
PreviousUSDXMintingRewardAccrualTimeKeyPrefix = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix PreviousUSDXMintingRewardAccrualTimeKeyPrefix = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix
HardLiquidityClaimKeyPrefix = types.HardLiquidityClaimKeyPrefix HardLiquidityClaimKeyPrefix = types.HardLiquidityClaimKeyPrefix
HardSupplyRewardIndexesKeyPrefix = types.HardSupplyRewardIndexesKeyPrefix HardSupplyRewardIndexesKeyPrefix = types.HardSupplyRewardIndexesKeyPrefix
PreviousHardSupplyRewardAccrualTimeKeyPrefix = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix PreviousHardSupplyRewardAccrualTimeKeyPrefix = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix
HardBorrowRewardIndexesKeyPrefix = types.HardBorrowRewardIndexesKeyPrefix HardBorrowRewardIndexesKeyPrefix = types.HardBorrowRewardIndexesKeyPrefix
PreviousHardBorrowRewardAccrualTimeKeyPrefix = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix PreviousHardBorrowRewardAccrualTimeKeyPrefix = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix
HardDelegatorRewardIndexesKeyPrefix = types.HardDelegatorRewardIndexesKeyPrefix DelegatorRewardIndexesKeyPrefix = types.DelegatorRewardIndexesKeyPrefix
PreviousHardDelegatorRewardAccrualTimeKeyPrefix = types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix PreviousDelegatorRewardAccrualTimeKeyPrefix = types.PreviousDelegatorRewardAccrualTimeKeyPrefix
USDXMintingRewardDenom = types.USDXMintingRewardDenom USDXMintingRewardDenom = types.USDXMintingRewardDenom
HardLiquidityRewardDenom = types.HardLiquidityRewardDenom HardLiquidityRewardDenom = types.HardLiquidityRewardDenom
KeyUSDXMintingRewardPeriods = types.KeyUSDXMintingRewardPeriods KeyUSDXMintingRewardPeriods = types.KeyUSDXMintingRewardPeriods
KeyHardSupplyRewardPeriods = types.KeyHardSupplyRewardPeriods KeyHardSupplyRewardPeriods = types.KeyHardSupplyRewardPeriods
KeyHardBorrowRewardPeriods = types.KeyHardBorrowRewardPeriods KeyHardBorrowRewardPeriods = types.KeyHardBorrowRewardPeriods
KeyHardDelegatorRewardPeriods = types.KeyHardDelegatorRewardPeriods KeyDelegatorRewardPeriods = types.KeyDelegatorRewardPeriods
KeyClaimEnd = types.KeyClaimEnd KeyClaimEnd = types.KeyClaimEnd
KeyMultipliers = types.KeyMultipliers KeyMultipliers = types.KeyMultipliers
DefaultActive = types.DefaultActive DefaultActive = types.DefaultActive
DefaultRewardPeriods = types.DefaultRewardPeriods DefaultRewardPeriods = types.DefaultRewardPeriods
DefaultMultiRewardPeriods = types.DefaultMultiRewardPeriods DefaultMultiRewardPeriods = types.DefaultMultiRewardPeriods
DefaultMultipliers = types.DefaultMultipliers DefaultMultipliers = types.DefaultMultipliers
DefaultUSDXClaims = types.DefaultUSDXClaims DefaultDelegatorClaims = types.DefaultDelegatorClaims
DefaultHardClaims = types.DefaultHardClaims DefaultUSDXClaims = types.DefaultUSDXClaims
DefaultGenesisAccumulationTimes = types.DefaultGenesisAccumulationTimes DefaultHardClaims = types.DefaultHardClaims
DefaultClaimEnd = types.DefaultClaimEnd DefaultGenesisAccumulationTimes = types.DefaultGenesisAccumulationTimes
GovDenom = types.GovDenom DefaultClaimEnd = types.DefaultClaimEnd
PrincipalDenom = types.PrincipalDenom GovDenom = types.GovDenom
IncentiveMacc = types.IncentiveMacc PrincipalDenom = types.PrincipalDenom
IncentiveMacc = types.IncentiveMacc
) )
type ( 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 --owner kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw
$ %s query %s rewards --type hard $ %s query %s rewards --type hard
$ %s query %s rewards --type usdx-minting $ %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 --owner kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw
$ %s query %s rewards --type hard --unsynced true $ %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, version.ClientName, types.ModuleName)), version.ClientName, types.ModuleName, version.ClientName, types.ModuleName,
version.ClientName, types.ModuleName)),
Args: cobra.NoArgs, Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc) cliCtx := context.NewCLIContext().WithCodec(cdc)
@ -106,9 +108,26 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
} }
} }
return cliCtx.PrintOutput(claims) 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: default:
var hardClaims types.HardLiquidityProviderClaims var hardClaims types.HardLiquidityProviderClaims
var usdxMintingClaims types.USDXMintingClaims var usdxMintingClaims types.USDXMintingClaims
var delegatorClaims types.DelegatorClaims
if boolUnsynced { if boolUnsynced {
paramsHard := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner) paramsHard := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner)
hardClaims, err = executeHardRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, paramsHard) hardClaims, err = executeHardRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, paramsHard)
@ -120,6 +139,11 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
paramsDelegator := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner)
delegatorClaims, err = executeDelegatorRewardsUnsyncedQuery(queryRoute, cdc, cliCtx, paramsDelegator)
if err != nil {
return err
}
} else { } else {
paramsHard := types.NewQueryHardRewardsParams(page, limit, owner) paramsHard := types.NewQueryHardRewardsParams(page, limit, owner)
hardClaims, err = executeHardRewardsQuery(queryRoute, cdc, cliCtx, paramsHard) hardClaims, err = executeHardRewardsQuery(queryRoute, cdc, cliCtx, paramsHard)
@ -131,6 +155,11 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
if err != nil { if err != nil {
return err return err
} }
paramsDelegator := types.NewQueryDelegatorRewardsParams(page, limit, owner)
delegatorClaims, err = executeDelegatorRewardsQuery(queryRoute, cdc, cliCtx, paramsDelegator)
if err != nil {
return err
}
} }
if len(hardClaims) > 0 { if len(hardClaims) > 0 {
cliCtx.PrintOutput(hardClaims) cliCtx.PrintOutput(hardClaims)
@ -138,6 +167,9 @@ func queryRewardsCmd(queryRoute string, cdc *codec.Codec) *cobra.Command {
if len(usdxMintingClaims) > 0 { if len(usdxMintingClaims) > 0 {
cliCtx.PrintOutput(usdxMintingClaims) cliCtx.PrintOutput(usdxMintingClaims)
} }
if len(delegatorClaims) > 0 {
cliCtx.PrintOutput(delegatorClaims)
}
} }
return nil return nil
}, },
@ -311,3 +343,49 @@ func executeUSDXMintingRewardsUnsyncedQuery(queryRoute string, cdc *codec.Codec,
return claims, nil 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), getCmdClaimCdpVVesting(cdc),
getCmdClaimHard(cdc), getCmdClaimHard(cdc),
getCmdClaimHardVVesting(cdc), getCmdClaimHardVVesting(cdc),
getCmdClaimDelegator(cdc),
getCmdClaimDelegatorVVesting(cdc),
)...) )...)
return incentiveTxCmd 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": case "usdx_minting":
params := types.NewQueryUSDXMintingRewardsUnsyncedParams(page, limit, owner) params := types.NewQueryUSDXMintingRewardsUnsyncedParams(page, limit, owner)
executeUSDXMintingRewardsUnsyncedQuery(w, cliCtx, params) executeUSDXMintingRewardsUnsyncedQuery(w, cliCtx, params)
case "delegator":
params := types.NewQueryDelegatorRewardsUnsyncedParams(page, limit, owner)
executeDelegatorRewardsUnsyncedQuery(w, cliCtx, params)
default: default:
hardParams := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner) hardParams := types.NewQueryHardRewardsUnsyncedParams(page, limit, owner)
usdxMintingParams := types.NewQueryUSDXMintingRewardsUnsyncedParams(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 { } else {
switch strings.ToLower(rewardType) { switch strings.ToLower(rewardType) {
@ -79,10 +83,14 @@ func queryRewardsHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
case "usdx_minting": case "usdx_minting":
params := types.NewQueryUSDXMintingRewardsParams(page, limit, owner) params := types.NewQueryUSDXMintingRewardsParams(page, limit, owner)
executeUSDXMintingRewardsQuery(w, cliCtx, params) executeUSDXMintingRewardsQuery(w, cliCtx, params)
case "delegator":
params := types.NewQueryDelegatorRewardsParams(page, limit, owner)
executeDelegatorRewardsQuery(w, cliCtx, params)
default: default:
hardParams := types.NewQueryHardRewardsParams(page, limit, owner) hardParams := types.NewQueryHardRewardsParams(page, limit, owner)
usdxMintingParams := types.NewQueryUSDXMintingRewardsParams(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) rest.PostProcessResponse(w, cliCtx, res)
} }
func executeBothRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, func executeDelegatorRewardsQuery(w http.ResponseWriter, cliCtx context.CLIContext, params types.QueryDelegatorRewardsParams) {
hardParams types.QueryHardRewardsParams, usdxMintingParams types.QueryUSDXMintingRewardsParams) { 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) hardBz, err := cliCtx.Codec.MarshalJSON(hardParams)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) 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 var usdxMintingClaims types.USDXMintingClaims
cliCtx.Codec.MustUnmarshalJSON(usdxMintingRes, &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) cliCtx = cliCtx.WithHeight(height)
type rewardResult struct { type rewardResult struct {
HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"` HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"`
UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"`
DelegatorClaims types.DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"`
} }
res := rewardResult{ res := rewardResult{
HardClaims: hardClaims, HardClaims: hardClaims,
UsdxMintingClaims: usdxMintingClaims, UsdxMintingClaims: usdxMintingClaims,
DelegatorClaims: delegatorClaims,
} }
resBz, err := cliCtx.Codec.MarshalJSON(res) resBz, err := cliCtx.Codec.MarshalJSON(res)
@ -265,8 +324,9 @@ func executeBothRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext,
rest.PostProcessResponse(w, cliCtx, resBz) rest.PostProcessResponse(w, cliCtx, resBz)
} }
func executeBothUnsyncedRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext, func executeAllUnsyncedRewardQueries(w http.ResponseWriter, cliCtx context.CLIContext,
hardParams types.QueryHardRewardsUnsyncedParams, usdxMintingParams types.QueryUSDXMintingRewardsUnsyncedParams) { hardParams types.QueryHardRewardsUnsyncedParams, usdxMintingParams types.QueryUSDXMintingRewardsUnsyncedParams,
delegatorParams types.QueryDelegatorRewardsUnsyncedParams) {
hardBz, err := cliCtx.Codec.MarshalJSON(hardParams) hardBz, err := cliCtx.Codec.MarshalJSON(hardParams)
if err != nil { if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to marshal query params: %s", err)) 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 var usdxMintingClaims types.USDXMintingClaims
cliCtx.Codec.MustUnmarshalJSON(usdxMintingRes, &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) cliCtx = cliCtx.WithHeight(height)
type rewardResult struct { type rewardResult struct {
HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"` HardClaims types.HardLiquidityProviderClaims `json:"hard_claims" yaml:"hard_claims"`
UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` UsdxMintingClaims types.USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"`
DelegatorClaims types.DelegatorClaims `json:"delegator_claims" yaml:"delegator_claims"`
} }
res := rewardResult{ res := rewardResult{
HardClaims: hardClaims, HardClaims: hardClaims,
UsdxMintingClaims: usdxMintingClaims, UsdxMintingClaims: usdxMintingClaims,
DelegatorClaims: delegatorClaims,
} }
resBz, err := cliCtx.Codec.MarshalJSON(res) 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-cdp-vesting", postClaimCdpVVestingHandlerFn(cliCtx)).Methods("POST")
r.HandleFunc("/incentive/claim-hard", postClaimHardHandlerFn(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-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 { 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}) 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) k.SetHardBorrowRewardIndexes(ctx, mrp.CollateralType, newRewardIndexes)
} }
for _, drp := range gs.Params.HardDelegatorRewardPeriods { for _, drp := range gs.Params.DelegatorRewardPeriods {
newRewardIndexes := types.RewardIndexes{} newRewardIndexes := types.RewardIndexes{}
for _, rc := range drp.RewardsPerSecond { for _, rc := range drp.RewardsPerSecond {
ri := types.NewRewardIndex(rc.Denom, sdk.ZeroDec()) ri := types.NewRewardIndex(rc.Denom, sdk.ZeroDec())
newRewardIndexes = append(newRewardIndexes, ri) newRewardIndexes = append(newRewardIndexes, ri)
} }
k.SetHardDelegatorRewardIndexes(ctx, drp.CollateralType, newRewardIndexes) k.SetDelegatorRewardIndexes(ctx, drp.CollateralType, newRewardIndexes)
} }
k.SetParams(ctx, gs.Params) 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) k.SetPreviousHardBorrowRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime)
} }
for _, gat := range gs.HardDelegatorAccumulationTimes { for _, gat := range gs.DelegatorAccumulationTimes {
k.SetPreviousHardDelegatorRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) k.SetPreviousDelegatorRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime)
} }
for _, gat := range gs.SwapAccumulationTimes { for _, gat := range gs.SwapAccumulationTimes {
k.SetSwapRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) 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 { k.SetHardLiquidityProviderClaim(ctx, claim)
for k, ri := range dri.RewardIndexes { }
for i, claim := range gs.DelegatorClaims {
for j, mri := range claim.RewardIndexes {
for k, ri := range mri.RewardIndexes {
if ri.RewardFactor != sdk.ZeroDec() { 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) usdxClaims := k.GetAllUSDXMintingClaims(ctx)
hardClaims := k.GetAllHardLiquidityProviderClaims(ctx) hardClaims := k.GetAllHardLiquidityProviderClaims(ctx)
delegatorClaims := k.GetAllDelegatorClaims(ctx)
synchronizedUsdxClaims := types.USDXMintingClaims{} synchronizedUsdxClaims := types.USDXMintingClaims{}
synchronizedHardClaims := types.HardLiquidityProviderClaims{} synchronizedHardClaims := types.HardLiquidityProviderClaims{}
synchronizedDelegatorClaims := types.DelegatorClaims{}
for _, usdxClaim := range usdxClaims { for _, usdxClaim := range usdxClaims {
claim, err := k.SynchronizeUSDXMintingClaim(ctx, usdxClaim) 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() claim.SupplyRewardIndexes[i].RewardIndexes[j].RewardFactor = sdk.ZeroDec()
} }
} }
for i, dri := range claim.DelegatorRewardIndexes { synchronizedHardClaims = append(synchronizedHardClaims, claim)
for j := range dri.RewardIndexes { }
claim.DelegatorRewardIndexes[i].RewardIndexes[j].RewardFactor = sdk.ZeroDec()
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 var usdxMintingGats GenesisAccumulationTimes
@ -188,14 +202,14 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
hardBorrowGats = append(hardBorrowGats, gat) hardBorrowGats = append(hardBorrowGats, gat)
} }
var hardDelegatorGats GenesisAccumulationTimes var delegatorGats GenesisAccumulationTimes
for _, rp := range params.HardDelegatorRewardPeriods { for _, rp := range params.DelegatorRewardPeriods {
pat, found := k.GetPreviousHardDelegatorRewardAccrualTime(ctx, rp.CollateralType) pat, found := k.GetPreviousDelegatorRewardAccrualTime(ctx, rp.CollateralType)
if !found { 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) gat := types.NewGenesisAccumulationTime(rp.CollateralType, pat)
hardDelegatorGats = append(hardDelegatorGats, gat) delegatorGats = append(delegatorGats, gat)
} }
var swapGats GenesisAccumulationTimes var swapGats GenesisAccumulationTimes
@ -209,5 +223,6 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
} }
return types.NewGenesisState(params, usdxMintingGats, hardSupplyGats, 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.DefaultGenesisAccumulationTimes,
incentive.DefaultUSDXClaims, incentive.DefaultUSDXClaims,
incentive.DefaultHardClaims, incentive.DefaultHardClaims,
incentive.DefaultDelegatorClaims,
) )
tApp.InitializeFromGenesisStatesWithTime( tApp.InitializeFromGenesisStatesWithTime(
suite.genesisTime, suite.genesisTime,

View File

@ -21,6 +21,10 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return handleMsgClaimHardReward(ctx, k, msg) return handleMsgClaimHardReward(ctx, k, msg)
case types.MsgClaimHardRewardVVesting: case types.MsgClaimHardRewardVVesting:
return handleMsgClaimHardRewardVVesting(ctx, k, msg) return handleMsgClaimHardRewardVVesting(ctx, k, msg)
case types.MsgClaimDelegatorReward:
return handleMsgClaimDelegatorReward(ctx, k, msg)
case types.MsgClaimDelegatorRewardVVesting:
return handleMsgClaimDelegatorRewardVVesting(ctx, k, msg)
default: default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) 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(), Events: ctx.EventManager().Events(),
}, nil }, 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.DefaultGenesisAccumulationTimes,
incentive.DefaultUSDXClaims, incentive.DefaultUSDXClaims,
incentive.DefaultHardClaims, incentive.DefaultHardClaims,
incentive.DefaultDelegatorClaims,
) )
tApp.InitializeFromGenesisStates(authGS, app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(incentiveGS)}, NewCDPGenStateMulti(), NewPricefeedGenStateMulti()) 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())} rewardPeriod := types.RewardIndexes{types.NewRewardIndex("bnb-s", sdk.ZeroDec())}
multiRewardIndex := types.NewMultiRewardIndex("bnb-s", rewardPeriod) multiRewardIndex := types.NewMultiRewardIndex("bnb-s", rewardPeriod)
multiRewardIndexes := types.MultiRewardIndexes{multiRewardIndex} 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.NotPanics(func() {
suite.keeper.SetHardLiquidityProviderClaim(suite.ctx, c1) suite.keeper.SetHardLiquidityProviderClaim(suite.ctx, c1)
}) })
@ -108,6 +109,8 @@ func (suite *HandlerTestSuite) addUSDXMintingClaim() {
}) })
} }
// TODO: add tests
func TestHandlerTestSuite(t *testing.T) { func TestHandlerTestSuite(t *testing.T) {
suite.Run(t, new(HandlerTestSuite)) 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 // BeforeDelegationCreated runs before a delegation is created
func (h Hooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { 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. // 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 // BeforeDelegationSharesModified runs before an existing delegation is modified
func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { func (h Hooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
// Sync rewards based on total delegated to bonded validators. // 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 // 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. // Sync all claims for users delegated to this validator.
// For each claim, sync based on the total delegated to bonded validators. // For each claim, sync based on the total delegated to bonded validators.
for _, delegation := range h.k.stakingKeeper.GetValidatorDelegations(ctx, valAddr) { 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. // 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. // 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) { 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. // 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 // 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) { 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 { 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) accumulationTimeForPeriod := types.NewGenesisAccumulationTime(period.CollateralType, builder.genesisTime)
builder.HardDelegatorAccumulationTimes = append(builder.HardDelegatorAccumulationTimes, accumulationTimeForPeriod) builder.DelegatorAccumulationTimes = append(builder.DelegatorAccumulationTimes, accumulationTimeForPeriod)
return builder return builder
} }

View File

@ -210,6 +210,55 @@ func (k Keeper) GetAllHardLiquidityProviderClaims(ctx sdk.Context) types.HardLiq
return cs 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 // SetHardSupplyRewardIndexes sets the current reward indexes for an individual denom
func (k Keeper) SetHardSupplyRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) { func (k Keeper) SetHardSupplyRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) {
store := prefix.NewStore(ctx.KVStore(k.key), types.HardSupplyRewardIndexesKeyPrefix) 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 // GetDelegatorRewardIndexes gets the current reward indexes for an individual denom
func (k Keeper) GetHardDelegatorRewardIndexes(ctx sdk.Context, denom string) (types.RewardIndexes, bool) { func (k Keeper) GetDelegatorRewardIndexes(ctx sdk.Context, denom string) (types.RewardIndexes, bool) {
store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix) store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorRewardIndexesKeyPrefix)
bz := store.Get([]byte(denom)) bz := store.Get([]byte(denom))
if bz == nil { if bz == nil {
return types.RewardIndexes{}, false return types.RewardIndexes{}, false
@ -288,16 +337,16 @@ func (k Keeper) GetHardDelegatorRewardIndexes(ctx sdk.Context, denom string) (ty
return rewardIndexes, true return rewardIndexes, true
} }
// SetHardDelegatorRewardIndexes sets the current reward indexes for an individual denom // SetDelegatorRewardIndexes sets the current reward indexes for an individual denom
func (k Keeper) SetHardDelegatorRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) { func (k Keeper) SetDelegatorRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) {
store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix) store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorRewardIndexesKeyPrefix)
bz := k.cdc.MustMarshalBinaryBare(indexes) bz := k.cdc.MustMarshalBinaryBare(indexes)
store.Set([]byte(denom), bz) store.Set([]byte(denom), bz)
} }
// IterateHardDelegatorRewardIndexes iterates over all Delegator reward index objects in the store and preforms a callback function // IterateDelegatorRewardIndexes 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)) { func (k Keeper) IterateDelegatorRewardIndexes(ctx sdk.Context, cb func(denom string, indexes types.RewardIndexes) (stop bool)) {
store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix) store := prefix.NewStore(ctx.KVStore(k.key), types.DelegatorRewardIndexesKeyPrefix)
iterator := sdk.KVStorePrefixIterator(store, []byte{}) iterator := sdk.KVStorePrefixIterator(store, []byte{})
defer iterator.Close() defer iterator.Close()
for ; iterator.Valid(); iterator.Next() { 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)) store.Set([]byte(denom), k.cdc.MustMarshalBinaryBare(blockTime))
} }
// GetPreviousHardDelegatorRewardAccrualTime returns the last time a denom accrued Hard protocol delegator rewards // GetPreviousDelegatorRewardAccrualTime returns the last time a denom accrued protocol delegator rewards
func (k Keeper) GetPreviousHardDelegatorRewardAccrualTime(ctx sdk.Context, denom string) (blockTime time.Time, found bool) { func (k Keeper) GetPreviousDelegatorRewardAccrualTime(ctx sdk.Context, denom string) (blockTime time.Time, found bool) {
store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix) store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousDelegatorRewardAccrualTimeKeyPrefix)
bz := store.Get([]byte(denom)) bz := store.Get([]byte(denom))
if bz == nil { if bz == nil {
return time.Time{}, false return time.Time{}, false
@ -354,9 +403,9 @@ func (k Keeper) GetPreviousHardDelegatorRewardAccrualTime(ctx sdk.Context, denom
return blockTime, true return blockTime, true
} }
// SetPreviousHardDelegatorRewardAccrualTime sets the last time a denom accrued Hard protocol delegator rewards // SetPreviousDelegatorRewardAccrualTime sets the last time a denom accrued protocol delegator rewards
func (k Keeper) SetPreviousHardDelegatorRewardAccrualTime(ctx sdk.Context, denom string, blockTime time.Time) { func (k Keeper) SetPreviousDelegatorRewardAccrualTime(ctx sdk.Context, denom string, blockTime time.Time) {
store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix) store := prefix.NewStore(ctx.KVStore(k.key), types.PreviousDelegatorRewardAccrualTimeKeyPrefix)
store.Set([]byte(denom), k.cdc.MustMarshalBinaryBare(blockTime)) 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 return types.MultiRewardPeriod{}, false
} }
// GetHardDelegatorRewardPeriod returns the reward period with the specified collateral type if it's found in the params // GetDelegatorRewardPeriods 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) { func (k Keeper) GetDelegatorRewardPeriods(ctx sdk.Context, denom string) (types.MultiRewardPeriod, bool) {
params := k.GetParams(ctx) params := k.GetParams(ctx)
for _, rp := range params.HardDelegatorRewardPeriods { for _, rp := range params.DelegatorRewardPeriods {
if rp.CollateralType == denom { if rp.CollateralType == denom {
return rp, true return rp, true
} }

View File

@ -193,7 +193,7 @@ func (k Keeper) ClaimHardReward(ctx sdk.Context, addr sdk.AccAddress, multiplier
return nil 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 { func (k Keeper) ClaimHardRewardVVesting(ctx sdk.Context, owner, receiver sdk.AccAddress, multiplierName types.MultiplierName) error {
_, found := k.GetHardLiquidityProviderClaim(ctx, owner) _, found := k.GetHardLiquidityProviderClaim(ctx, owner)
if !found { if !found {
@ -261,6 +261,129 @@ func (k Keeper) ClaimHardRewardVVesting(ctx sdk.Context, owner, receiver sdk.Acc
return nil 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. // 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 { func (k Keeper) SendTimeLockedCoinsToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, length int64) error {
macc := k.supplyKeeper.GetModuleAccount(ctx, senderModule) macc := k.supplyKeeper.GetModuleAccount(ctx, senderModule)

View File

@ -25,6 +25,10 @@ func NewQuerier(k Keeper) sdk.Querier {
return queryGetUSDXMintingRewards(ctx, req, k) return queryGetUSDXMintingRewards(ctx, req, k)
case types.QueryGetUSDXMintingRewardsUnsynced: case types.QueryGetUSDXMintingRewardsUnsynced:
return queryGetUSDXMintingRewardsUnsynced(ctx, req, k) return queryGetUSDXMintingRewardsUnsynced(ctx, req, k)
case types.QueryGetDelegatorRewards:
return queryGetDelegatorRewards(ctx, req, k)
case types.QueryGetDelegatorRewardsUnsynced:
return queryGetDelegatorRewardsUnsynced(ctx, req, k)
case types.QueryGetRewardFactors: case types.QueryGetRewardFactors:
return queryGetRewardFactors(ctx, req, k) return queryGetRewardFactors(ctx, req, k)
default: default:
@ -198,6 +202,82 @@ func queryGetUSDXMintingRewardsUnsynced(ctx sdk.Context, req abci.RequestQuery,
return bz, nil 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) { func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, error) {
var params types.QueryRewardFactorsParams var params types.QueryRewardFactorsParams
err := types.ModuleCdc.UnmarshalJSON(req.Data, &params) err := types.ModuleCdc.UnmarshalJSON(req.Data, &params)
@ -223,9 +303,9 @@ func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]
if found { if found {
rewardFactor.HardBorrowRewardFactors = hardBorrowRewardIndexes rewardFactor.HardBorrowRewardFactors = hardBorrowRewardIndexes
} }
hardDelegatorRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, params.Denom) delegatorRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, params.Denom)
if found { if found {
rewardFactor.HardDelegatorRewardFactors = hardDelegatorRewardIndexes rewardFactor.DelegatorRewardFactors = delegatorRewardIndexes
} }
rewardFactors = append(rewardFactors, rewardFactor) rewardFactors = append(rewardFactors, rewardFactor)
} else { } else {
@ -262,13 +342,13 @@ func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]
return false return false
}) })
// Populate mapping with Hard delegator reward factors // Populate mapping with delegator reward factors
k.IterateHardDelegatorRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) { k.IterateDelegatorRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) {
rewardFactor, ok := rewardFactorMap[denom] rewardFactor, ok := rewardFactorMap[denom]
if !ok { if !ok {
rewardFactor = types.RewardFactor{Denom: denom, HardDelegatorRewardFactors: indexes} rewardFactor = types.RewardFactor{Denom: denom, DelegatorRewardFactors: indexes}
} else { } else {
rewardFactor.HardDelegatorRewardFactors = indexes rewardFactor.DelegatorRewardFactors = indexes
} }
rewardFactorMap[denom] = rewardFactor rewardFactorMap[denom] = rewardFactor
return false 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) { func (k Keeper) InitializeHardBorrowReward(ctx sdk.Context, borrow hardtypes.Borrow) {
claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower) claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower)
if !found { 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 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) { func (k Keeper) UpdateHardBorrowIndexDenoms(ctx sdk.Context, borrow hardtypes.Borrow) {
claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower) claim, found := k.GetHardLiquidityProviderClaim(ctx, borrow.Borrower)
if !found { 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) borrowDenoms := getDenoms(borrow.Amount)

View File

@ -36,7 +36,7 @@ func (suite *InitializeHardBorrowRewardTests) TestClaimIndexesAreSetWhenClaimExi
// which means UpdateHardBorrowIndexDenoms was called and should have remove indexes. // which means UpdateHardBorrowIndexDenoms was called and should have remove indexes.
BorrowRewardIndexes: types.MultiRewardIndexes{}, BorrowRewardIndexes: types.MultiRewardIndexes{},
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := nonEmptyMultiRewardIndexes globalIndexes := nonEmptyMultiRewardIndexes
suite.storeGlobalBorrowIndexes(globalIndexes) suite.storeGlobalBorrowIndexes(globalIndexes)

View File

@ -39,7 +39,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestClaimIndexesAreUpdatedWhenGlo
}, },
BorrowRewardIndexes: nonEmptyMultiRewardIndexes, BorrowRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := increaseAllRewardFactors(nonEmptyMultiRewardIndexes) globalIndexes := increaseAllRewardFactors(nonEmptyMultiRewardIndexes)
suite.storeGlobalBorrowIndexes(globalIndexes) suite.storeGlobalBorrowIndexes(globalIndexes)
@ -64,7 +64,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestClaimIndexesAreUnchangedWhenG
}, },
BorrowRewardIndexes: unchangingIndexes, BorrowRewardIndexes: unchangingIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
suite.storeGlobalBorrowIndexes(unchangingIndexes) suite.storeGlobalBorrowIndexes(unchangingIndexes)
@ -88,7 +88,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestClaimIndexesAreUpdatedWhenNew
}, },
BorrowRewardIndexes: nonEmptyMultiRewardIndexes, BorrowRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := appendUniqueMultiRewardIndex(nonEmptyMultiRewardIndexes) globalIndexes := appendUniqueMultiRewardIndex(nonEmptyMultiRewardIndexes)
suite.storeGlobalBorrowIndexes(globalIndexes) suite.storeGlobalBorrowIndexes(globalIndexes)
@ -114,7 +114,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestClaimIndexesAreUpdatedWhenNew
}, },
BorrowRewardIndexes: nonEmptyMultiRewardIndexes, BorrowRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := appendUniqueRewardIndexToFirstItem(nonEmptyMultiRewardIndexes) globalIndexes := appendUniqueRewardIndexToFirstItem(nonEmptyMultiRewardIndexes)
suite.storeGlobalBorrowIndexes(globalIndexes) suite.storeGlobalBorrowIndexes(globalIndexes)
@ -155,7 +155,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestRewardIsIncrementedWhenGlobal
}, },
}, },
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
suite.storeGlobalBorrowIndexes(types.MultiRewardIndexes{ suite.storeGlobalBorrowIndexes(types.MultiRewardIndexes{
{ {
@ -206,7 +206,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestRewardIsIncrementedWhenNewRew
}, },
}, },
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := types.MultiRewardIndexes{ globalIndexes := types.MultiRewardIndexes{
{ {
@ -269,7 +269,7 @@ func (suite *SynchronizeHardBorrowRewardTests) TestRewardIsIncrementedWhenNewRew
}, },
}, },
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := types.MultiRewardIndexes{ globalIndexes := types.MultiRewardIndexes{
{ {

View File

@ -33,7 +33,7 @@ func (suite *UpdateHardBorrowIndexDenomsTests) TestClaimIndexesAreRemovedForDeno
}, },
BorrowRewardIndexes: nonEmptyMultiRewardIndexes, BorrowRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
suite.storeGlobalBorrowIndexes(claim.BorrowRewardIndexes) suite.storeGlobalBorrowIndexes(claim.BorrowRewardIndexes)
// remove one denom from the indexes already in the borrow // remove one denom from the indexes already in the borrow
@ -56,7 +56,7 @@ func (suite *UpdateHardBorrowIndexDenomsTests) TestClaimIndexesAreAddedForNewlyB
}, },
BorrowRewardIndexes: nonEmptyMultiRewardIndexes, BorrowRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := appendUniqueMultiRewardIndex(claim.BorrowRewardIndexes) globalIndexes := appendUniqueMultiRewardIndex(claim.BorrowRewardIndexes)
suite.storeGlobalBorrowIndexes(globalIndexes) suite.storeGlobalBorrowIndexes(globalIndexes)
@ -78,7 +78,7 @@ func (suite *UpdateHardBorrowIndexDenomsTests) TestClaimIndexesAreUnchangedWhenB
}, },
BorrowRewardIndexes: nonEmptyMultiRewardIndexes, BorrowRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
// Set global indexes with same denoms but different values. // Set global indexes with same denoms but different values.
// UpdateHardBorrowIndexDenoms should ignore the new values. // UpdateHardBorrowIndexDenoms should ignore the new values.
suite.storeGlobalBorrowIndexes(increaseAllRewardFactors(claim.BorrowRewardIndexes)) suite.storeGlobalBorrowIndexes(increaseAllRewardFactors(claim.BorrowRewardIndexes))
@ -101,7 +101,7 @@ func (suite *UpdateHardBorrowIndexDenomsTests) TestEmptyClaimIndexesAreAddedForN
}, },
BorrowRewardIndexes: nonEmptyMultiRewardIndexes, BorrowRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
suite.storeGlobalBorrowIndexes(claim.BorrowRewardIndexes) suite.storeGlobalBorrowIndexes(claim.BorrowRewardIndexes)
// add a denom to the borrowed amount that is not in the global or claim's indexes // 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" "github.com/kava-labs/kava/x/incentive/types"
) )
// AccumulateHardDelegatorRewards updates the rewards accumulated for the input reward period // AccumulateDelegatorRewards updates the rewards accumulated for the input reward period
func (k Keeper) AccumulateHardDelegatorRewards(ctx sdk.Context, rewardPeriods types.MultiRewardPeriod) error { func (k Keeper) AccumulateDelegatorRewards(ctx sdk.Context, rewardPeriods types.MultiRewardPeriod) error {
previousAccrualTime, found := k.GetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType) previousAccrualTime, found := k.GetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType)
if !found { if !found {
k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) k.SetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime())
return nil return nil
} }
timeElapsed := CalculateTimeElapsed(rewardPeriods.Start, rewardPeriods.End, ctx.BlockTime(), previousAccrualTime) timeElapsed := CalculateTimeElapsed(rewardPeriods.Start, rewardPeriods.End, ctx.BlockTime(), previousAccrualTime)
@ -20,23 +20,23 @@ func (k Keeper) AccumulateHardDelegatorRewards(ctx sdk.Context, rewardPeriods ty
return nil return nil
} }
if rewardPeriods.RewardsPerSecond.IsZero() { if rewardPeriods.RewardsPerSecond.IsZero() {
k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) k.SetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime())
return nil return nil
} }
totalBonded := k.stakingKeeper.TotalBondedTokens(ctx).ToDec() totalBonded := k.stakingKeeper.TotalBondedTokens(ctx).ToDec()
if totalBonded.IsZero() { if totalBonded.IsZero() {
k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) k.SetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime())
return nil return nil
} }
previousRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType) previousRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType)
if !found { if !found {
for _, rewardCoin := range rewardPeriods.RewardsPerSecond { for _, rewardCoin := range rewardPeriods.RewardsPerSecond {
rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec()) rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
previousRewardIndexes = append(previousRewardIndexes, rewardIndex) previousRewardIndexes = append(previousRewardIndexes, rewardIndex)
} }
k.SetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, previousRewardIndexes) k.SetDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, previousRewardIndexes)
} }
newRewardIndexes := previousRewardIndexes newRewardIndexes := previousRewardIndexes
@ -58,42 +58,53 @@ func (k Keeper) AccumulateHardDelegatorRewards(ctx sdk.Context, rewardPeriods ty
newRewardIndexes = append(newRewardIndexes, newRewardIndex) newRewardIndexes = append(newRewardIndexes, newRewardIndex)
} }
} }
k.SetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, newRewardIndexes) k.SetDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, newRewardIndexes)
k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime()) k.SetPreviousDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime())
return nil return nil
} }
// InitializeHardDelegatorReward initializes the delegator reward index of a hard claim // InitializeDelegatorReward initializes the reward index of a delegator claim
func (k Keeper) InitializeHardDelegatorReward(ctx sdk.Context, delegator sdk.AccAddress) { func (k Keeper) InitializeDelegatorReward(ctx sdk.Context, delegator sdk.AccAddress) {
claim, found := k.GetHardLiquidityProviderClaim(ctx, delegator) claim, found := k.GetDelegatorClaim(ctx, delegator)
if !found { if !found {
claim = types.NewHardLiquidityProviderClaim(delegator, sdk.Coins{}, nil, nil, nil) claim = types.NewDelegatorClaim(delegator, sdk.Coins{}, nil)
} else { } else {
k.SynchronizeHardDelegatorRewards(ctx, delegator, nil, false) k.SynchronizeDelegatorRewards(ctx, delegator, nil, false)
claim, _ = k.GetHardLiquidityProviderClaim(ctx, delegator) claim, _ = k.GetDelegatorClaim(ctx, delegator)
} }
var delegatorRewardIndexes types.MultiRewardIndexes var rewardIndexes types.MultiRewardIndexes
globalRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, types.BondDenom) globalRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, types.BondDenom)
if !found { if !found {
globalRewardIndexes = types.RewardIndexes{} globalRewardIndexes = types.RewardIndexes{}
} }
delegatorRewardIndexes = delegatorRewardIndexes.With(types.BondDenom, globalRewardIndexes) rewardIndexes = rewardIndexes.With(types.BondDenom, globalRewardIndexes)
claim.RewardIndexes = rewardIndexes
claim.DelegatorRewardIndexes = delegatorRewardIndexes k.SetDelegatorClaim(ctx, claim)
k.SetHardLiquidityProviderClaim(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. // 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). // Normally only delegations to Bonded validators are included in the total. This is needed as staking hooks are sometimes called on the wrong
func (k Keeper) SynchronizeHardDelegatorRewards(ctx sdk.Context, delegator sdk.AccAddress, valAddr sdk.ValAddress, shouldIncludeValidator bool) { // side of a validator's state update (from this module's perspective).
claim, found := k.GetHardLiquidityProviderClaim(ctx, delegator) func (k Keeper) SynchronizeDelegatorRewards(ctx sdk.Context, delegator sdk.AccAddress, valAddr sdk.ValAddress, shouldIncludeValidator bool) {
claim, found := k.GetDelegatorClaim(ctx, delegator)
if !found { if !found {
return return
} }
globalRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, types.BondDenom) globalRewardIndexes, found := k.GetDelegatorRewardIndexes(ctx, types.BondDenom)
if !found { if !found {
// The global factor is only not found if // 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) // - 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 return
} }
userRewardIndexes, found := claim.DelegatorRewardIndexes.Get(types.BondDenom) userRewardIndexes, found := claim.RewardIndexes.Get(types.BondDenom)
if !found { if !found {
// Normally the reward indexes should always be 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. // 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.Reward = claim.Reward.Add(rewardsEarned...)
claim.DelegatorRewardIndexes = claim.DelegatorRewardIndexes.With(types.BondDenom, globalRewardIndexes) claim.RewardIndexes = claim.RewardIndexes.With(types.BondDenom, globalRewardIndexes)
k.SetHardLiquidityProviderClaim(ctx, claim) k.SetDelegatorClaim(ctx, claim)
} }
func (k Keeper) GetTotalDelegated(ctx sdk.Context, delegator sdk.AccAddress, valAddr sdk.ValAddress, shouldIncludeValidator bool) sdk.Dec { 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 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" "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 // inputs
// - claim in store if it exists (only claim.DelegatorRewardIndexes) // - claim in store if it exists (only claim.DelegatorRewardIndexes)
@ -19,27 +19,33 @@ import (
// //
// outputs // outputs
// - sets or creates a claim // - sets or creates a claim
type InitializeHardDelegatorRewardTests struct { type InitializeDelegatorRewardTests struct {
unitTester unitTester
} }
func TestInitializeHardDelegatorReward(t *testing.T) { func TestInitializeDelegatorReward(t *testing.T) {
suite.Run(t, new(InitializeHardDelegatorRewardTests)) 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 globalIndex := arbitraryDelegatorRewardIndexes
suite.storeGlobalDelegatorIndexes(globalIndex) suite.storeGlobalDelegatorIndexes(globalIndex)
delegator := arbitraryAddress() 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.True(f)
suite.Equal(globalIndex, syncedClaim.DelegatorRewardIndexes) suite.Equal(globalIndex, syncedClaim.RewardIndexes)
} }
func (suite *InitializeHardDelegatorRewardTests) TestClaimIsSyncedAndIndexesAreSetWhenClaimDoesExist() { func (suite *InitializeDelegatorRewardTests) TestClaimIsSyncedAndIndexesAreSetWhenClaimDoesExist() {
validatorAddress := arbitraryValidatorAddress() validatorAddress := arbitraryValidatorAddress()
sk := fakeStakingKeeper{ sk := fakeStakingKeeper{
delegations: stakingtypes.Delegations{{ delegations: stakingtypes.Delegations{{
@ -55,28 +61,28 @@ func (suite *InitializeHardDelegatorRewardTests) TestClaimIsSyncedAndIndexesAreS
} }
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, sk, nil) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, sk, nil)
claim := types.HardLiquidityProviderClaim{ claim := types.DelegatorClaim{
BaseMultiClaim: types.BaseMultiClaim{ BaseMultiClaim: types.BaseMultiClaim{
Owner: arbitraryAddress(), 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 // Set the global factor to a value different to one in claim so
// we can detect if it is overwritten. // we can detect if it is overwritten.
rewardIndexes, _ := claim.DelegatorRewardIndexes.Get(types.BondDenom) rewardIndexes, _ := claim.RewardIndexes.Get(types.BondDenom)
globalIndexes := increaseRewardFactors(rewardIndexes) globalIndexes := increaseRewardFactors(rewardIndexes)
// Update the claim object with the new global factor // Update the claim object with the new global factor
bondIndex, _ := claim.DelegatorRewardIndexes.GetRewardIndexIndex(types.BondDenom) bondIndex, _ := claim.RewardIndexes.GetRewardIndexIndex(types.BondDenom)
claim.DelegatorRewardIndexes[bondIndex].RewardIndexes = globalIndexes claim.RewardIndexes[bondIndex].RewardIndexes = globalIndexes
suite.storeGlobalDelegatorIndexes(claim.DelegatorRewardIndexes) 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) syncedClaim, _ := suite.keeper.GetDelegatorClaim(suite.ctx, claim.Owner)
suite.Equal(globalIndexes, syncedClaim.DelegatorRewardIndexes[bondIndex].RewardIndexes) suite.Equal(globalIndexes, syncedClaim.RewardIndexes[bondIndex].RewardIndexes)
suite.Truef(syncedClaim.Reward.IsAllGT(claim.Reward), "'%s' not greater than '%s'", syncedClaim.Reward, claim.Reward) 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" "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 // inputs
// - claim in store if it exists (only claim.DelegatorRewardIndexes and claim.Reward) // - claim in store if it exists (only claim.DelegatorRewardIndexes and claim.Reward)
@ -20,64 +20,69 @@ import (
// //
// outputs // outputs
// - sets or creates a claim // - sets or creates a claim
type SynchronizeHardDelegatorRewardTests struct { type SynchronizeDelegatorRewardTests struct {
unitTester unitTester
} }
func TestSynchronizeHardDelegatorReward(t *testing.T) { func TestSynchronizeDelegatorReward(t *testing.T) {
suite.Run(t, new(SynchronizeHardDelegatorRewardTests)) 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() delegator := arbitraryAddress()
stakingKeeper := fakeStakingKeeper{} // use an empty staking keeper that returns no delegations stakingKeeper := fakeStakingKeeper{} // use an empty staking keeper that returns no delegations
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil)
claim := types.HardLiquidityProviderClaim{ claim := types.DelegatorClaim{
BaseMultiClaim: types.BaseMultiClaim{ BaseMultiClaim: types.BaseMultiClaim{
Owner: delegator, 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) syncedClaim, _ := suite.keeper.GetDelegatorClaim(suite.ctx, claim.Owner)
suite.Equal(claim.DelegatorRewardIndexes, syncedClaim.DelegatorRewardIndexes) suite.Equal(claim.RewardIndexes, syncedClaim.RewardIndexes)
} }
func (suite *SynchronizeHardDelegatorRewardTests) TestClaimIndexesAreUpdatedWhenGlobalFactorIncreased() { func (suite *SynchronizeDelegatorRewardTests) TestClaimIndexesAreUpdatedWhenGlobalFactorIncreased() {
delegator := arbitraryAddress() delegator := arbitraryAddress()
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, fakeStakingKeeper{}, nil) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, fakeStakingKeeper{}, nil)
claim := types.HardLiquidityProviderClaim{ claim := types.DelegatorClaim{
BaseMultiClaim: types.BaseMultiClaim{ BaseMultiClaim: types.BaseMultiClaim{
Owner: delegator, 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) globalIndexes := increaseRewardFactors(rewardIndexes)
// Update the claim object with the new global factor // Update the claim object with the new global factor
bondIndex, _ := claim.DelegatorRewardIndexes.GetRewardIndexIndex(types.BondDenom) bondIndex, _ := claim.RewardIndexes.GetRewardIndexIndex(types.BondDenom)
claim.DelegatorRewardIndexes[bondIndex].RewardIndexes = globalIndexes claim.RewardIndexes[bondIndex].RewardIndexes = globalIndexes
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(globalIndexes, syncedClaim.DelegatorRewardIndexes[bondIndex].RewardIndexes) suite.Equal(globalIndexes, syncedClaim.RewardIndexes[bondIndex].RewardIndexes)
} }
func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsUnchangedWhenGlobalFactorUnchanged() { func (suite *SynchronizeDelegatorRewardTests) TestRewardIsUnchangedWhenGlobalFactorUnchanged() {
delegator := arbitraryAddress() delegator := arbitraryAddress()
validatorAddress := arbitraryValidatorAddress() validatorAddress := arbitraryValidatorAddress()
stakingKeeper := fakeStakingKeeper{ stakingKeeper := fakeStakingKeeper{
@ -94,12 +99,12 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsUnchangedWhenGloba
} }
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil)
claim := types.HardLiquidityProviderClaim{ claim := types.DelegatorClaim{
BaseMultiClaim: types.BaseMultiClaim{ BaseMultiClaim: types.BaseMultiClaim{
Owner: delegator, Owner: delegator,
Reward: arbitraryCoins(), Reward: arbitraryCoins(),
}, },
DelegatorRewardIndexes: types.MultiRewardIndexes{{ RewardIndexes: types.MultiRewardIndexes{{
CollateralType: types.BondDenom, CollateralType: types.BondDenom,
RewardIndexes: types.RewardIndexes{ 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) suite.Equal(claim.Reward, syncedClaim.Reward)
} }
func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRewardAdded() { func (suite *SynchronizeDelegatorRewardTests) TestRewardIsIncreasedWhenNewRewardAdded() {
delegator := arbitraryAddress() delegator := arbitraryAddress()
validatorAddress := arbitraryValidatorAddress() validatorAddress := arbitraryValidatorAddress()
stakingKeeper := fakeStakingKeeper{ stakingKeeper := fakeStakingKeeper{
@ -139,14 +144,14 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRe
} }
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil)
claim := types.HardLiquidityProviderClaim{ claim := types.DelegatorClaim{
BaseMultiClaim: types.BaseMultiClaim{ BaseMultiClaim: types.BaseMultiClaim{
Owner: delegator, Owner: delegator,
Reward: arbitraryCoins(), Reward: arbitraryCoins(),
}, },
DelegatorRewardIndexes: types.MultiRewardIndexes{}, RewardIndexes: types.MultiRewardIndexes{},
} }
suite.storeClaim(claim) suite.storeDelegatorClaim(claim)
newGlobalIndexes := types.MultiRewardIndexes{{ newGlobalIndexes := types.MultiRewardIndexes{{
CollateralType: types.BondDenom, CollateralType: types.BondDenom,
@ -161,11 +166,11 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRe
}} }}
suite.storeGlobalDelegatorIndexes(newGlobalIndexes) 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( suite.Equal(
cs( cs(
c(types.HardLiquidityRewardDenom, 100), c(types.HardLiquidityRewardDenom, 100),
@ -175,7 +180,7 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRe
) )
} }
func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGlobalFactorIncreased() { func (suite *SynchronizeDelegatorRewardTests) TestRewardIsIncreasedWhenGlobalFactorIncreased() {
delegator := arbitraryAddress() delegator := arbitraryAddress()
validatorAddress := arbitraryValidatorAddress() validatorAddress := arbitraryValidatorAddress()
stakingKeeper := fakeStakingKeeper{ stakingKeeper := fakeStakingKeeper{
@ -192,12 +197,12 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGloba
} }
suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil) suite.keeper = suite.NewKeeper(&fakeParamSubspace{}, nil, nil, nil, nil, stakingKeeper, nil)
claim := types.HardLiquidityProviderClaim{ claim := types.DelegatorClaim{
BaseMultiClaim: types.BaseMultiClaim{ BaseMultiClaim: types.BaseMultiClaim{
Owner: delegator, Owner: delegator,
Reward: arbitraryCoins(), Reward: arbitraryCoins(),
}, },
DelegatorRewardIndexes: types.MultiRewardIndexes{{ RewardIndexes: types.MultiRewardIndexes{{
CollateralType: types.BondDenom, CollateralType: types.BondDenom,
RewardIndexes: types.RewardIndexes{ RewardIndexes: types.RewardIndexes{
{ {
@ -209,7 +214,7 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGloba
}, },
}}, }},
} }
suite.storeClaim(claim) suite.storeDelegatorClaim(claim)
suite.storeGlobalDelegatorIndexes( suite.storeGlobalDelegatorIndexes(
types.MultiRewardIndexes{ 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( suite.Equal(
cs( 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 // when valAddr is nil, get total delegated to bonded validators
delegator := arbitraryAddress() delegator := arbitraryAddress()
validatorAddresses := generateValidatorAddresses(4) validatorAddresses := generateValidatorAddresses(4)
@ -306,7 +311,7 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestGetDelegatedWhenValAddrIsN
suite.keeper.GetTotalDelegated(suite.ctx, delegator, nil, false), 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 // when valAddr is x, get total delegated to bonded validators excluding those to x
delegator := arbitraryAddress() delegator := arbitraryAddress()
validatorAddresses := generateValidatorAddresses(4) validatorAddresses := generateValidatorAddresses(4)
@ -349,7 +354,7 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestGetDelegatedWhenExcludingA
suite.keeper.GetTotalDelegated(suite.ctx, delegator, validatorAddresses[0], false), 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 // when valAddr is x, get total delegated to bonded validators including those to x
delegator := arbitraryAddress() delegator := arbitraryAddress()
validatorAddresses := generateValidatorAddresses(4) 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 { type args struct {
delegation sdk.Coin delegation sdk.Coin
rewardsPerSecond sdk.Coins rewardsPerSecond sdk.Coins
@ -145,18 +145,18 @@ func (suite *DelegatorRewardsTestSuite) TestAccumulateHardDelegatorRewards() {
runAtTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * tc.args.timeElapsed)) runAtTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * tc.args.timeElapsed))
runCtx := suite.ctx.WithBlockTime(runAtTime) 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) suite.Require().True(found)
err = suite.keeper.AccumulateHardDelegatorRewards(runCtx, rewardPeriods) err = suite.keeper.AccumulateDelegatorRewards(runCtx, rewardPeriods)
suite.Require().NoError(err) 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) suite.Require().Equal(tc.args.expectedRewardIndexes, rewardIndexes)
}) })
} }
} }
func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() { func (suite *DelegatorRewardsTestSuite) TestSynchronizeDelegatorReward() {
type args struct { type args struct {
delegation sdk.Coin delegation sdk.Coin
rewardsPerSecond sdk.Coins rewardsPerSecond sdk.Coins
@ -249,10 +249,10 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
suite.Require().Equal(valAcc.Status, sdk.Bonded) suite.Require().Equal(valAcc.Status, sdk.Bonded)
suite.Require().Equal(valAcc.Tokens, tc.args.delegation.Amount.Add(selfDelegationCoins.Amount)) suite.Require().Equal(valAcc.Tokens, tc.args.delegation.Amount.Add(selfDelegationCoins.Amount))
// Check that Staking hooks initialized a HardLiquidityProviderClaim // Check that Staking hooks initialized a DelegatorClaim
claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) claim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0])
suite.Require().True(found) 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) suite.Require().Equal(sdk.ZeroDec(), rewardIndex.RewardFactor)
} }
@ -265,10 +265,10 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
previousBlockTime = updatedBlockTime previousBlockTime = updatedBlockTime
blockCtx := suite.ctx.WithBlockTime(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) suite.Require().True(found)
err := suite.keeper.AccumulateHardDelegatorRewards(blockCtx, rewardPeriods) err := suite.keeper.AccumulateDelegatorRewards(blockCtx, rewardPeriods)
suite.Require().NoError(err) suite.Require().NoError(err)
} }
updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed)) 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 // After we've accumulated, run synchronize
suite.Require().NotPanics(func() { 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 // 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 { for i, rewardPerSecond := range tc.args.rewardsPerSecond {
rewardFactor, _ := rewardIndexes.Get(rewardPerSecond.Denom) rewardFactor, _ := rewardIndexes.Get(rewardPerSecond.Denom)
suite.Require().Equal(tc.args.expectedRewardIndexes[i].RewardFactor, rewardFactor) 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) 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.expectedRewardIndexes[i].RewardFactor, delegatorRewardIndex.RewardFactor)
} }
suite.Require().Equal(tc.args.expectedRewards, claim.Reward) 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 { type args struct {
delegation sdk.Coin delegation sdk.Coin
rewardsPerSecond sdk.Coins rewardsPerSecond sdk.Coins
@ -365,10 +365,10 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni
staking.EndBlocker(suite.ctx, suite.stakingKeeper) staking.EndBlocker(suite.ctx, suite.stakingKeeper)
// Check that Staking hooks initialized a HardLiquidityProviderClaim // Check that Staking hooks initialized a DelegatorClaim
claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0]) claim, found := suite.keeper.GetDelegatorClaim(suite.ctx, suite.addrs[0])
suite.Require().True(found) 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) suite.Require().Equal(sdk.ZeroDec(), rewardIndex.RewardFactor)
} }
@ -381,21 +381,21 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni
previousBlockTime = updatedBlockTime previousBlockTime = updatedBlockTime
blockCtx := suite.ctx.WithBlockTime(updatedBlockTime) blockCtx := suite.ctx.WithBlockTime(updatedBlockTime)
// Accumulate hard delegator rewards // Accumulate delegator rewards
rewardPeriods, found := suite.keeper.GetHardDelegatorRewardPeriods(blockCtx, tc.args.delegation.Denom) rewardPeriods, found := suite.keeper.GetDelegatorRewardPeriods(blockCtx, tc.args.delegation.Denom)
suite.Require().True(found) suite.Require().True(found)
err := suite.keeper.AccumulateHardDelegatorRewards(blockCtx, rewardPeriods) err := suite.keeper.AccumulateDelegatorRewards(blockCtx, rewardPeriods)
suite.Require().NoError(err) suite.Require().NoError(err)
} }
updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed)) updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed))
suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime) suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
// Check that the synced claim held in memory has properly simulated syncing // 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 { for i, expectedRewardIndex := range tc.args.expectedRewardIndexes {
// Check that the user's claim's reward index matches the expected reward index // 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().True(found)
suite.Require().Equal(expectedRewardIndex, multiRewardIndex[i]) 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. // 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 // 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) suite.Require().True(found)
rewardIndexes, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) rewardIndexes, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom)
suite.Require().True(found) suite.Require().True(found)
globalIndex, found := rewardIndexes.Get(rewardsPerSecond[0].Denom) globalIndex, found := rewardIndexes.Get(rewardsPerSecond[0].Denom)
suite.Require().True(found) suite.Require().True(found)
claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) claimIndex, found := claim.RewardIndexes.GetRewardIndex(bondDenom)
suite.Require().True(found) suite.Require().True(found)
suite.Require().Equal(globalIndex, claimIndex.RewardIndexes[0].RewardFactor) 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.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(3 * blockDuration))
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) _ = 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 // 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().True(found)
suite.Require().Equal(claim.Reward, laterClaim.Reward) suite.Require().Equal(claim.Reward, laterClaim.Reward)
// claim index has been updated to latest global value // 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) suite.Require().True(found)
rewardIndexes, found = suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) rewardIndexes, found = suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom)
suite.Require().True(found) suite.Require().True(found)
globalIndex, found = rewardIndexes.Get(rewardsPerSecond[0].Denom) globalIndex, found = rewardIndexes.Get(rewardsPerSecond[0].Denom)
suite.Require().True(found) 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. // 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 // 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) suite.Require().True(found)
rewardIndexes, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) rewardIndexes, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom)
suite.Require().True(found) suite.Require().True(found)
globalIndex, found := rewardIndexes.Get(rewardsPerSecond[0].Denom) globalIndex, found := rewardIndexes.Get(rewardsPerSecond[0].Denom)
suite.Require().True(found) suite.Require().True(found)
claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) claimIndex, found := claim.RewardIndexes.GetRewardIndex(bondDenom)
suite.Require().True(found) suite.Require().True(found)
suite.Require().Equal(globalIndex, claimIndex.RewardIndexes[0].RewardFactor) 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.ctx = suite.ctx.WithBlockTime(suite.genesisTime.Add(3 * blockDuration))
_ = suite.app.BeginBlocker(suite.ctx, abci.RequestBeginBlock{}) _ = 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 // 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(found)
suite.Require().True(laterClaim.Reward.IsAllGT(claim.Reward)) suite.Require().True(laterClaim.Reward.IsAllGT(claim.Reward))
// claim index has been updated to latest global value // 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) suite.Require().True(found)
rewardIndexes, found = suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) rewardIndexes, found = suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom)
suite.Require().True(found) suite.Require().True(found)
globalIndex, found = rewardIndexes.Get(rewardsPerSecond[0].Denom) globalIndex, found = rewardIndexes.Get(rewardsPerSecond[0].Denom)
suite.Require().True(found) suite.Require().True(found)
@ -674,11 +674,11 @@ func (suite *DelegatorRewardsTestSuite) TestSlashingValidatorSyncsClaim() {
suite.Require().NoError(err) suite.Require().NoError(err)
// Check that claim has been created with synced reward index but no reward coins // 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) suite.True(found)
initialGlobalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) initialGlobalIndex, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom)
suite.True(found) suite.True(found)
initialClaimIndex, found := initialClaim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) initialClaimIndex, found := initialClaim.RewardIndexes.GetRewardIndex(bondDenom)
suite.True(found) suite.True(found)
suite.Require().Equal(initialGlobalIndex, initialClaimIndex.RewardIndexes) suite.Require().Equal(initialGlobalIndex, initialClaimIndex.RewardIndexes)
suite.True(initialClaim.Reward.Empty()) // Initial claim should not have any rewards 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) 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 // 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) suite.Require().True(found)
globalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) globalIndex, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom)
suite.Require().True(found) suite.Require().True(found)
claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) claimIndex, found := claim.RewardIndexes.GetRewardIndex(bondDenom)
suite.Require().True(found) suite.Require().True(found)
suite.Require().Equal(globalIndex, claimIndex.RewardIndexes) suite.Require().Equal(globalIndex, claimIndex.RewardIndexes)
@ -754,12 +754,12 @@ func (suite *DelegatorRewardsTestSuite) TestRedelegationSyncsClaim() {
suite.Require().NoError(err) suite.Require().NoError(err)
// Check that the user's claim has been synced. ie rewards added, index updated // 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) suite.Require().True(found)
globalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom) globalIndex, found := suite.keeper.GetDelegatorRewardIndexes(suite.ctx, bondDenom)
suite.Require().True(found) suite.Require().True(found)
claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom) claimIndex, found := claim.RewardIndexes.GetRewardIndex(bondDenom)
suite.Require().True(found) suite.Require().True(found)
suite.Require().Equal(globalIndex, claimIndex.RewardIndexes) suite.Require().Equal(globalIndex, claimIndex.RewardIndexes)
suite.Require().Equal( 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) { func (k Keeper) InitializeHardSupplyReward(ctx sdk.Context, deposit hardtypes.Deposit) {
claim, found := k.GetHardLiquidityProviderClaim(ctx, deposit.Depositor) claim, found := k.GetHardLiquidityProviderClaim(ctx, deposit.Depositor)
if !found { 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 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) { func (k Keeper) UpdateHardSupplyIndexDenoms(ctx sdk.Context, deposit hardtypes.Deposit) {
claim, found := k.GetHardLiquidityProviderClaim(ctx, deposit.Depositor) claim, found := k.GetHardLiquidityProviderClaim(ctx, deposit.Depositor)
if !found { 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) depositDenoms := getDenoms(deposit.Amount)
@ -186,9 +186,6 @@ func (k Keeper) SynchronizeHardLiquidityProviderClaim(ctx sdk.Context, owner sdk
if foundBorrow { if foundBorrow {
k.SynchronizeHardBorrowReward(ctx, borrow) 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 // 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 return claim
} }

View File

@ -36,7 +36,7 @@ func (suite *InitializeHardSupplyRewardTests) TestClaimIndexesAreSetWhenClaimExi
// which means UpdateHardSupplyIndexDenoms was called and should have remove indexes. // which means UpdateHardSupplyIndexDenoms was called and should have remove indexes.
SupplyRewardIndexes: types.MultiRewardIndexes{}, SupplyRewardIndexes: types.MultiRewardIndexes{},
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := nonEmptyMultiRewardIndexes globalIndexes := nonEmptyMultiRewardIndexes
suite.storeGlobalSupplyIndexes(globalIndexes) suite.storeGlobalSupplyIndexes(globalIndexes)

View File

@ -35,7 +35,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestClaimIndexesAreUpdatedWhenGlo
}, },
SupplyRewardIndexes: nonEmptyMultiRewardIndexes, SupplyRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := increaseAllRewardFactors(nonEmptyMultiRewardIndexes) globalIndexes := increaseAllRewardFactors(nonEmptyMultiRewardIndexes)
suite.storeGlobalSupplyIndexes(globalIndexes) suite.storeGlobalSupplyIndexes(globalIndexes)
@ -60,7 +60,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestClaimIndexesAreUnchangedWhenG
}, },
SupplyRewardIndexes: unchangingIndexes, SupplyRewardIndexes: unchangingIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
suite.storeGlobalSupplyIndexes(unchangingIndexes) suite.storeGlobalSupplyIndexes(unchangingIndexes)
@ -84,7 +84,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestClaimIndexesAreUpdatedWhenNew
}, },
SupplyRewardIndexes: nonEmptyMultiRewardIndexes, SupplyRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := appendUniqueMultiRewardIndex(nonEmptyMultiRewardIndexes) globalIndexes := appendUniqueMultiRewardIndex(nonEmptyMultiRewardIndexes)
suite.storeGlobalSupplyIndexes(globalIndexes) suite.storeGlobalSupplyIndexes(globalIndexes)
@ -110,7 +110,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestClaimIndexesAreUpdatedWhenNew
}, },
SupplyRewardIndexes: nonEmptyMultiRewardIndexes, SupplyRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := appendUniqueRewardIndexToFirstItem(nonEmptyMultiRewardIndexes) globalIndexes := appendUniqueRewardIndexToFirstItem(nonEmptyMultiRewardIndexes)
suite.storeGlobalSupplyIndexes(globalIndexes) suite.storeGlobalSupplyIndexes(globalIndexes)
@ -151,7 +151,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestRewardIsIncrementedWhenGlobal
}, },
}, },
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
suite.storeGlobalSupplyIndexes(types.MultiRewardIndexes{ suite.storeGlobalSupplyIndexes(types.MultiRewardIndexes{
{ {
@ -202,7 +202,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestRewardIsIncrementedWhenNewRew
}, },
}, },
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := types.MultiRewardIndexes{ globalIndexes := types.MultiRewardIndexes{
{ {
@ -265,7 +265,7 @@ func (suite *SynchronizeHardSupplyRewardTests) TestRewardIsIncrementedWhenNewRew
}, },
}, },
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := types.MultiRewardIndexes{ globalIndexes := types.MultiRewardIndexes{
{ {

View File

@ -33,7 +33,7 @@ func (suite *UpdateHardSupplyIndexDenomsTests) TestClaimIndexesAreRemovedForDeno
}, },
SupplyRewardIndexes: nonEmptyMultiRewardIndexes, SupplyRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
suite.storeGlobalSupplyIndexes(claim.SupplyRewardIndexes) suite.storeGlobalSupplyIndexes(claim.SupplyRewardIndexes)
// remove one denom from the indexes already in the deposit // remove one denom from the indexes already in the deposit
@ -56,7 +56,7 @@ func (suite *UpdateHardSupplyIndexDenomsTests) TestClaimIndexesAreAddedForNewlyS
}, },
SupplyRewardIndexes: nonEmptyMultiRewardIndexes, SupplyRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
globalIndexes := appendUniqueMultiRewardIndex(claim.SupplyRewardIndexes) globalIndexes := appendUniqueMultiRewardIndex(claim.SupplyRewardIndexes)
suite.storeGlobalSupplyIndexes(globalIndexes) suite.storeGlobalSupplyIndexes(globalIndexes)
@ -78,7 +78,7 @@ func (suite *UpdateHardSupplyIndexDenomsTests) TestClaimIndexesAreUnchangedWhenS
}, },
SupplyRewardIndexes: nonEmptyMultiRewardIndexes, SupplyRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
// Set global indexes with same denoms but different values. // Set global indexes with same denoms but different values.
// UpdateHardSupplyIndexDenoms should ignore the new values. // UpdateHardSupplyIndexDenoms should ignore the new values.
suite.storeGlobalSupplyIndexes(increaseAllRewardFactors(claim.SupplyRewardIndexes)) suite.storeGlobalSupplyIndexes(increaseAllRewardFactors(claim.SupplyRewardIndexes))
@ -101,7 +101,7 @@ func (suite *UpdateHardSupplyIndexDenomsTests) TestEmptyClaimIndexesAreAddedForN
}, },
SupplyRewardIndexes: nonEmptyMultiRewardIndexes, SupplyRewardIndexes: nonEmptyMultiRewardIndexes,
} }
suite.storeClaim(claim) suite.storeHardClaim(claim)
suite.storeGlobalSupplyIndexes(claim.SupplyRewardIndexes) suite.storeGlobalSupplyIndexes(claim.SupplyRewardIndexes)
// add a denom to the deposited amount that is not in the global or claim's indexes // 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) { func (suite *unitTester) storeGlobalDelegatorIndexes(multiRewardIndexes types.MultiRewardIndexes) {
// Hardcoded to use bond denom // Hardcoded to use bond denom
multiRewardIndex, _ := multiRewardIndexes.GetRewardIndex(types.BondDenom) 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) { func (suite *unitTester) storeGlobalSwapIndexes(indexes types.MultiRewardIndexes) {
for _, i := range indexes { 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) suite.keeper.SetHardLiquidityProviderClaim(suite.ctx, claim)
} }
func (suite *unitTester) storeDelegatorClaim(claim types.DelegatorClaim) {
suite.keeper.SetDelegatorClaim(suite.ctx, claim)
}
type fakeParamSubspace struct { type fakeParamSubspace struct {
params types.Params params types.Params
} }

View File

@ -11,6 +11,7 @@ import (
const ( const (
USDXMintingClaimType = "usdx_minting" USDXMintingClaimType = "usdx_minting"
HardLiquidityProviderClaimType = "hard_liquidity_provider" HardLiquidityProviderClaimType = "hard_liquidity_provider"
DelegatorClaimType = "delegator_claim"
BondDenom = "ukava" BondDenom = "ukava"
) )
@ -163,23 +164,21 @@ func (cs USDXMintingClaims) Validate() error {
// HardLiquidityProviderClaim stores the hard liquidity provider rewards that can be claimed by owner // HardLiquidityProviderClaim stores the hard liquidity provider rewards that can be claimed by owner
type HardLiquidityProviderClaim struct { type HardLiquidityProviderClaim struct {
BaseMultiClaim `json:"base_claim" yaml:"base_claim"` BaseMultiClaim `json:"base_claim" yaml:"base_claim"`
SupplyRewardIndexes MultiRewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"` SupplyRewardIndexes MultiRewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"`
BorrowRewardIndexes MultiRewardIndexes `json:"borrow_reward_indexes" yaml:"borrow_reward_indexes"` BorrowRewardIndexes MultiRewardIndexes `json:"borrow_reward_indexes" yaml:"borrow_reward_indexes"`
DelegatorRewardIndexes MultiRewardIndexes `json:"delegator_reward_indexes" yaml:"delegator_reward_indexes"`
} }
// NewHardLiquidityProviderClaim returns a new HardLiquidityProviderClaim // NewHardLiquidityProviderClaim returns a new HardLiquidityProviderClaim
func NewHardLiquidityProviderClaim(owner sdk.AccAddress, rewards sdk.Coins, supplyRewardIndexes, func NewHardLiquidityProviderClaim(owner sdk.AccAddress, rewards sdk.Coins,
borrowRewardIndexes, delegatorRewardIndexes MultiRewardIndexes) HardLiquidityProviderClaim { supplyRewardIndexes, borrowRewardIndexes MultiRewardIndexes) HardLiquidityProviderClaim {
return HardLiquidityProviderClaim{ return HardLiquidityProviderClaim{
BaseMultiClaim: BaseMultiClaim{ BaseMultiClaim: BaseMultiClaim{
Owner: owner, Owner: owner,
Reward: rewards, Reward: rewards,
}, },
SupplyRewardIndexes: supplyRewardIndexes, SupplyRewardIndexes: supplyRewardIndexes,
BorrowRewardIndexes: borrowRewardIndexes, BorrowRewardIndexes: borrowRewardIndexes,
DelegatorRewardIndexes: delegatorRewardIndexes,
} }
} }
@ -202,10 +201,6 @@ func (c HardLiquidityProviderClaim) Validate() error {
return err return err
} }
if err := c.DelegatorRewardIndexes.Validate(); err != nil {
return err
}
return c.BaseMultiClaim.Validate() return c.BaseMultiClaim.Validate()
} }
@ -214,8 +209,7 @@ func (c HardLiquidityProviderClaim) String() string {
return fmt.Sprintf(`%s return fmt.Sprintf(`%s
Supply Reward Indexes: %s, Supply Reward Indexes: %s,
Borrow Reward Indexes: %s, Borrow Reward Indexes: %s,
Delegator Reward Indexes: %s, `, c.BaseMultiClaim, c.SupplyRewardIndexes, c.BorrowRewardIndexes)
`, c.BaseMultiClaim, c.SupplyRewardIndexes, c.BorrowRewardIndexes, c.DelegatorRewardIndexes)
} }
// HasSupplyRewardIndex check if a claim has a supply reward index for the input collateral type // 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 return 0, false
} }
// HasDelegatorRewardIndex check if a claim has a delegator reward index for the input collateral type // HardLiquidityProviderClaims slice of HardLiquidityProviderClaim
func (c HardLiquidityProviderClaim) HasDelegatorRewardIndex(collateralType string) (int64, bool) { type HardLiquidityProviderClaims []HardLiquidityProviderClaim
for index, ri := range c.DelegatorRewardIndexes {
// 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 { if ri.CollateralType == collateralType {
return int64(index), true return int64(index), true
} }
@ -248,12 +299,12 @@ func (c HardLiquidityProviderClaim) HasDelegatorRewardIndex(collateralType strin
return 0, false return 0, false
} }
// HardLiquidityProviderClaims slice of HardLiquidityProviderClaim // DelegatorClaim slice of DelegatorClaim
type HardLiquidityProviderClaims []HardLiquidityProviderClaim type DelegatorClaims []DelegatorClaim
// Validate checks if all the claims are valid and there are no duplicated // Validate checks if all the claims are valid and there are no duplicated
// entries. // entries.
func (cs HardLiquidityProviderClaims) Validate() error { func (cs DelegatorClaims) Validate() error {
for _, c := range cs { for _, c := range cs {
if err := c.Validate(); err != nil { if err := c.Validate(); err != nil {
return err return err

View File

@ -17,10 +17,13 @@ func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterInterface((*Claim)(nil), nil) cdc.RegisterInterface((*Claim)(nil), nil)
cdc.RegisterConcrete(USDXMintingClaim{}, "incentive/USDXMintingClaim", nil) cdc.RegisterConcrete(USDXMintingClaim{}, "incentive/USDXMintingClaim", nil)
cdc.RegisterConcrete(HardLiquidityProviderClaim{}, "incentive/HardLiquidityProviderClaim", nil) cdc.RegisterConcrete(HardLiquidityProviderClaim{}, "incentive/HardLiquidityProviderClaim", nil)
cdc.RegisterConcrete(DelegatorClaim{}, "incentive/DelegatorClaim", nil)
// Register msgs // Register msgs
cdc.RegisterConcrete(MsgClaimUSDXMintingReward{}, "incentive/MsgClaimUSDXMintingReward", nil) cdc.RegisterConcrete(MsgClaimUSDXMintingReward{}, "incentive/MsgClaimUSDXMintingReward", nil)
cdc.RegisterConcrete(MsgClaimHardReward{}, "incentive/MsgClaimHardReward", nil) cdc.RegisterConcrete(MsgClaimHardReward{}, "incentive/MsgClaimHardReward", nil)
cdc.RegisterConcrete(MsgClaimDelegatorReward{}, "incentive/MsgClaimDelegatorReward", nil)
cdc.RegisterConcrete(MsgClaimUSDXMintingRewardVVesting{}, "incentive/MsgClaimUSDXRewardVVesting", nil) cdc.RegisterConcrete(MsgClaimUSDXMintingRewardVVesting{}, "incentive/MsgClaimUSDXRewardVVesting", nil)
cdc.RegisterConcrete(MsgClaimHardRewardVVesting{}, "incentive/MsgClaimHardRewardVVesting", 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. // GenesisState is the state that must be provided at genesis.
type GenesisState struct { type GenesisState struct {
Params Params `json:"params" yaml:"params"` Params Params `json:"params" yaml:"params"`
USDXAccumulationTimes GenesisAccumulationTimes `json:"usdx_accumulation_times" yaml:"usdx_accumulation_times"` USDXAccumulationTimes GenesisAccumulationTimes `json:"usdx_accumulation_times" yaml:"usdx_accumulation_times"`
HardSupplyAccumulationTimes GenesisAccumulationTimes `json:"hard_supply_accumulation_times" yaml:"hard_supply_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"` HardBorrowAccumulationTimes GenesisAccumulationTimes `json:"hard_borrow_accumulation_times" yaml:"hard_borrow_accumulation_times"`
HardDelegatorAccumulationTimes GenesisAccumulationTimes `json:"hard_delegator_accumulation_times" yaml:"hard_delegator_accumulation_times"` DelegatorAccumulationTimes GenesisAccumulationTimes `json:"delegator_accumulation_times" yaml:"delegator_accumulation_times"`
SwapAccumulationTimes GenesisAccumulationTimes `json:"swap_accumulation_times" yaml:"swap_accumulation_times"` SwapAccumulationTimes GenesisAccumulationTimes `json:"swap_accumulation_times" yaml:"swap_accumulation_times"`
USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"`
HardLiquidityProviderClaims HardLiquidityProviderClaims `json:"hard_liquidity_provider_claims" yaml:"hard_liquidity_provider_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 // 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{ return GenesisState{
Params: params, Params: params,
USDXAccumulationTimes: usdxAccumTimes, USDXAccumulationTimes: usdxAccumTimes,
HardSupplyAccumulationTimes: hardSupplyAccumTimes, HardSupplyAccumulationTimes: hardSupplyAccumTimes,
HardBorrowAccumulationTimes: hardBorrowAccumTimes, HardBorrowAccumulationTimes: hardBorrowAccumTimes,
HardDelegatorAccumulationTimes: hardDelegatorAccumTimes, DelegatorAccumulationTimes: delegatorAccumTimes,
SwapAccumulationTimes: swapAccumTimes, SwapAccumulationTimes: swapAccumTimes,
USDXMintingClaims: c, USDXMintingClaims: c,
HardLiquidityProviderClaims: hc, HardLiquidityProviderClaims: hc,
DelegatorClaims: dc,
} }
} }
// DefaultGenesisState returns a default genesis state // DefaultGenesisState returns a default genesis state
func DefaultGenesisState() GenesisState { func DefaultGenesisState() GenesisState {
return GenesisState{ return GenesisState{
Params: DefaultParams(), Params: DefaultParams(),
USDXAccumulationTimes: GenesisAccumulationTimes{}, USDXAccumulationTimes: GenesisAccumulationTimes{},
HardSupplyAccumulationTimes: GenesisAccumulationTimes{}, HardSupplyAccumulationTimes: GenesisAccumulationTimes{},
HardBorrowAccumulationTimes: GenesisAccumulationTimes{}, HardBorrowAccumulationTimes: GenesisAccumulationTimes{},
HardDelegatorAccumulationTimes: GenesisAccumulationTimes{}, DelegatorAccumulationTimes: GenesisAccumulationTimes{},
SwapAccumulationTimes: GenesisAccumulationTimes{}, SwapAccumulationTimes: GenesisAccumulationTimes{},
USDXMintingClaims: DefaultUSDXClaims, USDXMintingClaims: DefaultUSDXClaims,
HardLiquidityProviderClaims: DefaultHardClaims, HardLiquidityProviderClaims: DefaultHardClaims,
DelegatorClaims: DefaultDelegatorClaims,
} }
} }
@ -61,7 +65,7 @@ func (gs GenesisState) Validate() error {
if err := gs.HardBorrowAccumulationTimes.Validate(); err != nil { if err := gs.HardBorrowAccumulationTimes.Validate(); err != nil {
return err return err
} }
if err := gs.HardDelegatorAccumulationTimes.Validate(); err != nil { if err := gs.DelegatorAccumulationTimes.Validate(); err != nil {
return err return err
} }
if err := gs.SwapAccumulationTimes.Validate(); err != nil { if err := gs.SwapAccumulationTimes.Validate(); err != nil {
@ -71,7 +75,10 @@ func (gs GenesisState) Validate() error {
if err := gs.HardLiquidityProviderClaims.Validate(); err != nil { if err := gs.HardLiquidityProviderClaims.Validate(); err != nil {
return err 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 // 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.genAccTimes,
tc.args.claims, tc.args.claims,
DefaultHardClaims, DefaultHardClaims,
DefaultDelegatorClaims,
) )
err := gs.Validate() err := gs.Validate()
if tc.errArgs.expectPass { if tc.errArgs.expectPass {

View File

@ -23,18 +23,19 @@ const (
// Key Prefixes // Key Prefixes
var ( var (
USDXMintingClaimKeyPrefix = []byte{0x01} // prefix for keys that store USDX minting claims USDXMintingClaimKeyPrefix = []byte{0x01} // prefix for keys that store USDX minting claims
USDXMintingRewardFactorKeyPrefix = []byte{0x02} // prefix for key that stores USDX minting reward factors USDXMintingRewardFactorKeyPrefix = []byte{0x02} // prefix for key that stores USDX minting reward factors
PreviousUSDXMintingRewardAccrualTimeKeyPrefix = []byte{0x03} // prefix for key that stores the blocktime PreviousUSDXMintingRewardAccrualTimeKeyPrefix = []byte{0x03} // prefix for key that stores the blocktime
HardLiquidityClaimKeyPrefix = []byte{0x04} // prefix for keys that store Hard liquidity claims HardLiquidityClaimKeyPrefix = []byte{0x04} // prefix for keys that store Hard liquidity claims
HardSupplyRewardIndexesKeyPrefix = []byte{0x05} // prefix for key that stores Hard supply reward indexes 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 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 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 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 DelegatorClaimKeyPrefix = []byte{0x09} // prefix for keys that store delegator claims
PreviousHardDelegatorRewardAccrualTimeKeyPrefix = []byte{0x10} // prefix for key that stores the previous time Hard delegator rewards accrued DelegatorRewardIndexesKeyPrefix = []byte{0x10} // prefix for key that stores delegator reward indexes
SwapRewardIndexesKeyPrefix = []byte{0x11} // prefix for key that stores swap reward indexes PreviousDelegatorRewardAccrualTimeKeyPrefix = []byte{0x11} // prefix for key that stores the previous time delegator rewards accrued
PreviousSwapRewardAccrualTimeKeyPrefix = []byte{0x12} // prefix for key that stores the previous time swap 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" USDXMintingRewardDenom = "ukava"
HardLiquidityRewardDenom = "hard" HardLiquidityRewardDenom = "hard"

View File

@ -146,7 +146,7 @@ type MsgClaimHardRewardVVesting struct {
MultiplierName string `json:"multiplier_name" yaml:"multiplier_name"` 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 { func NewMsgClaimHardRewardVVesting(sender, receiver sdk.AccAddress, multiplierName string) MsgClaimHardRewardVVesting {
return MsgClaimHardRewardVVesting{ return MsgClaimHardRewardVVesting{
Sender: sender, Sender: sender,
@ -184,3 +184,90 @@ func (msg MsgClaimHardRewardVVesting) GetSignBytes() []byte {
func (msg MsgClaimHardRewardVVesting) GetSigners() []sdk.AccAddress { func (msg MsgClaimHardRewardVVesting) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.Sender} 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") KeyUSDXMintingRewardPeriods = []byte("USDXMintingRewardPeriods")
KeyHardSupplyRewardPeriods = []byte("HardSupplyRewardPeriods") KeyHardSupplyRewardPeriods = []byte("HardSupplyRewardPeriods")
KeyHardBorrowRewardPeriods = []byte("HardBorrowRewardPeriods") KeyHardBorrowRewardPeriods = []byte("HardBorrowRewardPeriods")
KeyHardDelegatorRewardPeriods = []byte("HardDelegatorRewardPeriods") KeyDelegatorRewardPeriods = []byte("DelegatorRewardPeriods")
KeySwapRewardPeriods = []byte("SwapRewardPeriods") KeySwapRewardPeriods = []byte("SwapRewardPeriods")
KeyClaimEnd = []byte("ClaimEnd") KeyClaimEnd = []byte("ClaimEnd")
KeyMultipliers = []byte("ClaimMultipliers") KeyMultipliers = []byte("ClaimMultipliers")
@ -37,6 +37,7 @@ var (
DefaultMultipliers = Multipliers{} DefaultMultipliers = Multipliers{}
DefaultUSDXClaims = USDXMintingClaims{} DefaultUSDXClaims = USDXMintingClaims{}
DefaultHardClaims = HardLiquidityProviderClaims{} DefaultHardClaims = HardLiquidityProviderClaims{}
DefaultDelegatorClaims = DelegatorClaims{}
DefaultGenesisAccumulationTimes = GenesisAccumulationTimes{} DefaultGenesisAccumulationTimes = GenesisAccumulationTimes{}
DefaultClaimEnd = tmtime.Canonical(time.Unix(1, 0)) DefaultClaimEnd = tmtime.Canonical(time.Unix(1, 0))
GovDenom = cdptypes.DefaultGovDenom GovDenom = cdptypes.DefaultGovDenom
@ -46,26 +47,26 @@ var (
// Params governance parameters for the incentive module // Params governance parameters for the incentive module
type Params struct { type Params struct {
USDXMintingRewardPeriods RewardPeriods `json:"usdx_minting_reward_periods" yaml:"usdx_minting_reward_periods"` USDXMintingRewardPeriods RewardPeriods `json:"usdx_minting_reward_periods" yaml:"usdx_minting_reward_periods"`
HardSupplyRewardPeriods MultiRewardPeriods `json:"hard_supply_reward_periods" yaml:"hard_supply_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"` HardBorrowRewardPeriods MultiRewardPeriods `json:"hard_borrow_reward_periods" yaml:"hard_borrow_reward_periods"`
HardDelegatorRewardPeriods MultiRewardPeriods `json:"hard_delegator_reward_periods" yaml:"hard_delegator_reward_periods"` DelegatorRewardPeriods MultiRewardPeriods `json:"delegator_reward_periods" yaml:"delegator_reward_periods"`
SwapRewardPeriods MultiRewardPeriods `json:"swap_reward_periods" json:"swap_reward_periods"` SwapRewardPeriods MultiRewardPeriods `json:"swap_reward_periods" json:"swap_reward_periods"`
ClaimMultipliers Multipliers `json:"claim_multipliers" yaml:"claim_multipliers"` ClaimMultipliers Multipliers `json:"claim_multipliers" yaml:"claim_multipliers"`
ClaimEnd time.Time `json:"claim_end" yaml:"claim_end"` ClaimEnd time.Time `json:"claim_end" yaml:"claim_end"`
} }
// NewParams returns a new params object // 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 { multipliers Multipliers, claimEnd time.Time) Params {
return Params{ return Params{
USDXMintingRewardPeriods: usdxMinting, USDXMintingRewardPeriods: usdxMinting,
HardSupplyRewardPeriods: hardSupply, HardSupplyRewardPeriods: hardSupply,
HardBorrowRewardPeriods: hardBorrow, HardBorrowRewardPeriods: hardBorrow,
HardDelegatorRewardPeriods: hardDelegator, DelegatorRewardPeriods: delegator,
SwapRewardPeriods: swap, SwapRewardPeriods: swap,
ClaimMultipliers: multipliers, ClaimMultipliers: multipliers,
ClaimEnd: claimEnd, ClaimEnd: claimEnd,
} }
} }
@ -88,12 +89,12 @@ func (p Params) String() string {
USDX Minting Reward Periods: %s USDX Minting Reward Periods: %s
Hard Supply Reward Periods: %s Hard Supply Reward Periods: %s
Hard Borrow Reward Periods: %s Hard Borrow Reward Periods: %s
Hard Delegator Reward Periods: %s Delegator Reward Periods: %s
Swap Reward Periods: %s Swap Reward Periods: %s
Claim Multipliers :%s Claim Multipliers :%s
Claim End Time: %s Claim End Time: %s
`, p.USDXMintingRewardPeriods, p.HardSupplyRewardPeriods, p.HardBorrowRewardPeriods, `, 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 // ParamKeyTable Key declaration for parameters
@ -107,7 +108,7 @@ func (p *Params) ParamSetPairs() params.ParamSetPairs {
params.NewParamSetPair(KeyUSDXMintingRewardPeriods, &p.USDXMintingRewardPeriods, validateRewardPeriodsParam), params.NewParamSetPair(KeyUSDXMintingRewardPeriods, &p.USDXMintingRewardPeriods, validateRewardPeriodsParam),
params.NewParamSetPair(KeyHardSupplyRewardPeriods, &p.HardSupplyRewardPeriods, validateMultiRewardPeriodsParam), params.NewParamSetPair(KeyHardSupplyRewardPeriods, &p.HardSupplyRewardPeriods, validateMultiRewardPeriodsParam),
params.NewParamSetPair(KeyHardBorrowRewardPeriods, &p.HardBorrowRewardPeriods, 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(KeySwapRewardPeriods, &p.SwapRewardPeriods, validateMultiRewardPeriodsParam),
params.NewParamSetPair(KeyClaimEnd, &p.ClaimEnd, validateClaimEndParam), params.NewParamSetPair(KeyClaimEnd, &p.ClaimEnd, validateClaimEndParam),
params.NewParamSetPair(KeyMultipliers, &p.ClaimMultipliers, validateMultipliersParam), params.NewParamSetPair(KeyMultipliers, &p.ClaimMultipliers, validateMultipliersParam),
@ -133,7 +134,7 @@ func (p Params) Validate() error {
return err return err
} }
if err := validateMultiRewardPeriodsParam(p.HardDelegatorRewardPeriods); err != nil { if err := validateMultiRewardPeriodsParam(p.DelegatorRewardPeriods); err != nil {
return err return err
} }

View File

@ -70,11 +70,11 @@ func (suite *ParamTestSuite) TestParamValidation() {
types.Large, 1, sdk.MustNewDecFromStr("1.0"), types.Large, 1, sdk.MustNewDecFromStr("1.0"),
), ),
}, },
HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods,
HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods,
HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, DelegatorRewardPeriods: types.DefaultMultiRewardPeriods,
SwapRewardPeriods: types.DefaultMultiRewardPeriods, SwapRewardPeriods: types.DefaultMultiRewardPeriods,
ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC),
}, },
errArgs{ errArgs{
expectPass: true, expectPass: true,
@ -83,13 +83,13 @@ func (suite *ParamTestSuite) TestParamValidation() {
{ {
"invalid usdx minting period makes params invalid", "invalid usdx minting period makes params invalid",
types.Params{ types.Params{
USDXMintingRewardPeriods: types.RewardPeriods{rewardPeriodWithInvalidRewardsPerSecond}, USDXMintingRewardPeriods: types.RewardPeriods{rewardPeriodWithInvalidRewardsPerSecond},
HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods,
HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods,
HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, DelegatorRewardPeriods: types.DefaultMultiRewardPeriods,
SwapRewardPeriods: types.DefaultMultiRewardPeriods, SwapRewardPeriods: types.DefaultMultiRewardPeriods,
ClaimMultipliers: types.DefaultMultipliers, ClaimMultipliers: types.DefaultMultipliers,
ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC),
}, },
errArgs{ errArgs{
expectPass: false, expectPass: false,
@ -99,13 +99,13 @@ func (suite *ParamTestSuite) TestParamValidation() {
{ {
"invalid hard supply periods makes params invalid", "invalid hard supply periods makes params invalid",
types.Params{ types.Params{
USDXMintingRewardPeriods: types.DefaultRewardPeriods, USDXMintingRewardPeriods: types.DefaultRewardPeriods,
HardSupplyRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, HardSupplyRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond},
HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods,
HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, DelegatorRewardPeriods: types.DefaultMultiRewardPeriods,
SwapRewardPeriods: types.DefaultMultiRewardPeriods, SwapRewardPeriods: types.DefaultMultiRewardPeriods,
ClaimMultipliers: types.DefaultMultipliers, ClaimMultipliers: types.DefaultMultipliers,
ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC),
}, },
errArgs{ errArgs{
expectPass: false, expectPass: false,
@ -115,13 +115,13 @@ func (suite *ParamTestSuite) TestParamValidation() {
{ {
"invalid hard borrow periods makes params invalid", "invalid hard borrow periods makes params invalid",
types.Params{ types.Params{
USDXMintingRewardPeriods: types.DefaultRewardPeriods, USDXMintingRewardPeriods: types.DefaultRewardPeriods,
HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods,
HardBorrowRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, HardBorrowRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond},
HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, DelegatorRewardPeriods: types.DefaultMultiRewardPeriods,
SwapRewardPeriods: types.DefaultMultiRewardPeriods, SwapRewardPeriods: types.DefaultMultiRewardPeriods,
ClaimMultipliers: types.DefaultMultipliers, ClaimMultipliers: types.DefaultMultipliers,
ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC),
}, },
errArgs{ errArgs{
expectPass: false, expectPass: false,
@ -131,13 +131,13 @@ func (suite *ParamTestSuite) TestParamValidation() {
{ {
"invalid delegator periods makes params invalid", "invalid delegator periods makes params invalid",
types.Params{ types.Params{
USDXMintingRewardPeriods: types.DefaultRewardPeriods, USDXMintingRewardPeriods: types.DefaultRewardPeriods,
HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods,
HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods,
HardDelegatorRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, DelegatorRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond},
SwapRewardPeriods: types.DefaultMultiRewardPeriods, SwapRewardPeriods: types.DefaultMultiRewardPeriods,
ClaimMultipliers: types.DefaultMultipliers, ClaimMultipliers: types.DefaultMultipliers,
ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC),
}, },
errArgs{ errArgs{
expectPass: false, expectPass: false,
@ -147,13 +147,13 @@ func (suite *ParamTestSuite) TestParamValidation() {
{ {
"invalid swap periods makes params invalid", "invalid swap periods makes params invalid",
types.Params{ types.Params{
USDXMintingRewardPeriods: types.DefaultRewardPeriods, USDXMintingRewardPeriods: types.DefaultRewardPeriods,
HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods, HardSupplyRewardPeriods: types.DefaultMultiRewardPeriods,
HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods, HardBorrowRewardPeriods: types.DefaultMultiRewardPeriods,
HardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods, DelegatorRewardPeriods: types.DefaultMultiRewardPeriods,
SwapRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond}, SwapRewardPeriods: types.MultiRewardPeriods{rewardMultiPeriodWithInvalidRewardsPerSecond},
ClaimMultipliers: types.DefaultMultipliers, ClaimMultipliers: types.DefaultMultipliers,
ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC), ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC),
}, },
errArgs{ errArgs{
expectPass: false, expectPass: false,

View File

@ -11,6 +11,8 @@ const (
QueryGetHardRewardsUnsynced = "hard-rewards-unsynced" QueryGetHardRewardsUnsynced = "hard-rewards-unsynced"
QueryGetUSDXMintingRewards = "usdx-minting-rewards" QueryGetUSDXMintingRewards = "usdx-minting-rewards"
QueryGetUSDXMintingRewardsUnsynced = "usdx-minting-rewards-unsynced" QueryGetUSDXMintingRewardsUnsynced = "usdx-minting-rewards-unsynced"
QueryGetDelegatorRewards = "delegator-rewards"
QueryGetDelegatorRewardsUnsynced = "delegator-rewards-unsynced"
QueryGetRewardFactors = "reward-factors" QueryGetRewardFactors = "reward-factors"
QueryGetParams = "parameters" QueryGetParams = "parameters"
QueryGetRewardPeriods = "reward-periods" 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 // RewardFactor is a unique type returned by reward factor queries
type RewardFactor struct { type RewardFactor struct {
Denom string `json:"denom" yaml:"denom"` Denom string `json:"denom" yaml:"denom"`
USDXMintingRewardFactor sdk.Dec `json:"usdx_minting_reward_factor" yaml:"usdx_minting_reward_factor"` 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"` HardSupplyRewardFactors RewardIndexes `json:"hard_supply_reward_factors" yaml:"hard_supply_reward_factors"`
HardBorrowRewardFactors RewardIndexes `json:"hard_borrow_reward_factors" yaml:"hard_borrow_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"` DelegatorRewardFactors RewardIndexes `json:"delegator_reward_factors" yaml:"delegator_reward_factors"`
} }
// NewRewardFactor returns a new instance of RewardFactor // NewRewardFactor returns a new instance of RewardFactor
func NewRewardFactor(denom string, usdxMintingRewardFactor sdk.Dec, hardSupplyRewardFactors, func NewRewardFactor(denom string, usdxMintingRewardFactor sdk.Dec, hardSupplyRewardFactors,
hardBorrowRewardFactors, hardDelegatorRewardFactors RewardIndexes) RewardFactor { hardBorrowRewardFactors, delegatorRewardFactors RewardIndexes) RewardFactor {
return RewardFactor{ return RewardFactor{
Denom: denom, Denom: denom,
USDXMintingRewardFactor: usdxMintingRewardFactor, USDXMintingRewardFactor: usdxMintingRewardFactor,
HardSupplyRewardFactors: hardSupplyRewardFactors, HardSupplyRewardFactors: hardSupplyRewardFactors,
HardBorrowRewardFactors: hardBorrowRewardFactors, HardBorrowRewardFactors: hardBorrowRewardFactors,
HardDelegatorRewardFactors: hardDelegatorRewardFactors, DelegatorRewardFactors: delegatorRewardFactors,
} }
} }