mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 02:07:52 +00:00 
			
		
		
		
	Update delegator rewards to multi-reward index (#945)
* 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
This commit is contained in:
		
							parent
							
								
									baf17b4ec8
								
							
						
					
					
						commit
						bc33b94822
					
				@ -23,8 +23,8 @@ import (
 | 
			
		||||
	v0_14committee "github.com/kava-labs/kava/x/committee/legacy/v0_14"
 | 
			
		||||
	v0_14hard "github.com/kava-labs/kava/x/hard"
 | 
			
		||||
	v0_11hard "github.com/kava-labs/kava/x/hard/legacy/v0_11"
 | 
			
		||||
	v0_14incentive "github.com/kava-labs/kava/x/incentive"
 | 
			
		||||
	v0_11incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_11"
 | 
			
		||||
	v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
 | 
			
		||||
	"github.com/kava-labs/kava/x/kavadist"
 | 
			
		||||
	v0_11pricefeed "github.com/kava-labs/kava/x/pricefeed"
 | 
			
		||||
	v0_14pricefeed "github.com/kava-labs/kava/x/pricefeed"
 | 
			
		||||
 | 
			
		||||
@ -24,8 +24,8 @@ import (
 | 
			
		||||
	v0_14committee "github.com/kava-labs/kava/x/committee/legacy/v0_14"
 | 
			
		||||
	v0_14hard "github.com/kava-labs/kava/x/hard"
 | 
			
		||||
	v0_11hard "github.com/kava-labs/kava/x/hard/legacy/v0_11"
 | 
			
		||||
	v0_14incentive "github.com/kava-labs/kava/x/incentive"
 | 
			
		||||
	v0_11incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_11"
 | 
			
		||||
	v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
 | 
			
		||||
	v0_11pricefeed "github.com/kava-labs/kava/x/pricefeed"
 | 
			
		||||
	validatorvesting "github.com/kava-labs/kava/x/validator-vesting"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,13 +12,16 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	v0_14committee "github.com/kava-labs/kava/x/committee/legacy/v0_14"
 | 
			
		||||
	"github.com/kava-labs/kava/x/committee/types"
 | 
			
		||||
	v0_15committee "github.com/kava-labs/kava/x/committee/types"
 | 
			
		||||
	v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
 | 
			
		||||
	v0_15incentive "github.com/kava-labs/kava/x/incentive/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// TODO: update GenesisTime for kava-8 launch
 | 
			
		||||
	GenesisTime = time.Date(2021, 4, 8, 15, 0, 0, 0, time.UTC)
 | 
			
		||||
	// TODO: update SWP reward per second amount before production
 | 
			
		||||
	SwpRewardsPerSecond = sdk.NewCoin("swp", sdk.OneInt())
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Migrate translates a genesis file from kava v0.14 format to kava v0.15 format
 | 
			
		||||
@ -47,6 +50,15 @@ func Migrate(genDoc tmtypes.GenesisDoc) tmtypes.GenesisDoc {
 | 
			
		||||
// MigrateAppState migrates application state from v0.14 format to a kava v0.15 format
 | 
			
		||||
func MigrateAppState(v0_14AppState genutil.AppMap) genutil.AppMap {
 | 
			
		||||
	v0_15AppState := v0_14AppState
 | 
			
		||||
	cdc := app.MakeCodec()
 | 
			
		||||
 | 
			
		||||
	// Migrate incentive app state
 | 
			
		||||
	if v0_14AppState[v0_14incentive.ModuleName] != nil {
 | 
			
		||||
		var incentiveGenState v0_14incentive.GenesisState
 | 
			
		||||
		cdc.MustUnmarshalJSON(v0_14AppState[v0_15incentive.ModuleName], &incentiveGenState)
 | 
			
		||||
		delete(v0_14AppState, v0_14incentive.ModuleName)
 | 
			
		||||
		v0_15AppState[v0_15incentive.ModuleName] = cdc.MustMarshalJSON(Incentive(incentiveGenState))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Migrate commmittee app state
 | 
			
		||||
	if v0_14AppState[v0_14committee.ModuleName] != nil {
 | 
			
		||||
@ -75,7 +87,7 @@ func Committee(genesisState v0_14committee.GenesisState) v0_15committee.GenesisS
 | 
			
		||||
	for _, com := range genesisState.Committees {
 | 
			
		||||
		if com.ID == 1 {
 | 
			
		||||
			// Initialize member committee without permissions
 | 
			
		||||
			stabilityCom := types.NewMemberCommittee(com.ID, com.Description, com.Members,
 | 
			
		||||
			stabilityCom := v0_15committee.NewMemberCommittee(com.ID, com.Description, com.Members,
 | 
			
		||||
				[]v0_15committee.Permission{}, com.VoteThreshold, com.ProposalDuration,
 | 
			
		||||
				v0_15committee.FirstPastThePost)
 | 
			
		||||
 | 
			
		||||
@ -171,7 +183,7 @@ func Committee(genesisState v0_14committee.GenesisState) v0_15committee.GenesisS
 | 
			
		||||
			newStabilityCom := v0_15committee.MemberCommittee{BaseCommittee: baseStabilityCom}
 | 
			
		||||
			committees = append(committees, newStabilityCom)
 | 
			
		||||
		} else {
 | 
			
		||||
			safetyCom := types.NewMemberCommittee(com.ID, com.Description, com.Members,
 | 
			
		||||
			safetyCom := v0_15committee.NewMemberCommittee(com.ID, com.Description, com.Members,
 | 
			
		||||
				[]v0_15committee.Permission{v0_15committee.SoftwareUpgradePermission{}},
 | 
			
		||||
				com.VoteThreshold, com.ProposalDuration, v0_15committee.FirstPastThePost)
 | 
			
		||||
			committees = append(committees, safetyCom)
 | 
			
		||||
@ -179,7 +191,7 @@ func Committee(genesisState v0_14committee.GenesisState) v0_15committee.GenesisS
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, v := range genesisState.Votes {
 | 
			
		||||
		newVote := v0_15committee.NewVote(v.ProposalID, v.Voter, types.Yes)
 | 
			
		||||
		newVote := v0_15committee.NewVote(v.ProposalID, v.Voter, v0_15committee.Yes)
 | 
			
		||||
		votes = append(votes, v0_15committee.Vote(newVote))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -191,3 +203,141 @@ func Committee(genesisState v0_14committee.GenesisState) v0_15committee.GenesisS
 | 
			
		||||
	return v0_15committee.NewGenesisState(
 | 
			
		||||
		genesisState.NextProposalID, committees, proposals, votes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Incentive migrates from a v0.14 incentive genesis state to a v0.15 incentive genesis state
 | 
			
		||||
func Incentive(incentiveGS v0_14incentive.GenesisState) v0_15incentive.GenesisState {
 | 
			
		||||
	// Migrate params
 | 
			
		||||
	var claimMultipliers v0_15incentive.Multipliers
 | 
			
		||||
	for _, m := range incentiveGS.Params.ClaimMultipliers {
 | 
			
		||||
		newMultiplier := v0_15incentive.NewMultiplier(v0_15incentive.MultiplierName(m.Name), m.MonthsLockup, m.Factor)
 | 
			
		||||
		claimMultipliers = append(claimMultipliers, newMultiplier)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var usdxMintingRewardPeriods v0_15incentive.RewardPeriods
 | 
			
		||||
	for _, rp := range incentiveGS.Params.USDXMintingRewardPeriods {
 | 
			
		||||
		usdxMintingRewardPeriod := v0_15incentive.NewRewardPeriod(rp.Active,
 | 
			
		||||
			rp.CollateralType, rp.Start, rp.End, rp.RewardsPerSecond)
 | 
			
		||||
		usdxMintingRewardPeriods = append(usdxMintingRewardPeriods, usdxMintingRewardPeriod)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var hardSupplyRewardPeriods v0_15incentive.MultiRewardPeriods
 | 
			
		||||
	for _, rp := range incentiveGS.Params.HardSupplyRewardPeriods {
 | 
			
		||||
		hardSupplyRewardPeriod := v0_15incentive.NewMultiRewardPeriod(rp.Active,
 | 
			
		||||
			rp.CollateralType, rp.Start, rp.End, rp.RewardsPerSecond)
 | 
			
		||||
		hardSupplyRewardPeriods = append(hardSupplyRewardPeriods, hardSupplyRewardPeriod)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var hardBorrowRewardPeriods v0_15incentive.MultiRewardPeriods
 | 
			
		||||
	for _, rp := range incentiveGS.Params.HardBorrowRewardPeriods {
 | 
			
		||||
		hardBorrowRewardPeriod := v0_15incentive.NewMultiRewardPeriod(rp.Active,
 | 
			
		||||
			rp.CollateralType, rp.Start, rp.End, rp.RewardsPerSecond)
 | 
			
		||||
		hardBorrowRewardPeriods = append(hardBorrowRewardPeriods, hardBorrowRewardPeriod)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var hardDelegatorRewardPeriods v0_15incentive.MultiRewardPeriods
 | 
			
		||||
	for _, rp := range incentiveGS.Params.HardDelegatorRewardPeriods {
 | 
			
		||||
		rewardsPerSecond := sdk.NewCoins(rp.RewardsPerSecond, SwpRewardsPerSecond)
 | 
			
		||||
		hardDelegatorRewardPeriod := v0_15incentive.NewMultiRewardPeriod(rp.Active,
 | 
			
		||||
			rp.CollateralType, rp.Start, rp.End, rewardsPerSecond)
 | 
			
		||||
		hardDelegatorRewardPeriods = append(hardDelegatorRewardPeriods, hardDelegatorRewardPeriod)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Build new params from migrated values
 | 
			
		||||
	params := v0_15incentive.NewParams(
 | 
			
		||||
		usdxMintingRewardPeriods,
 | 
			
		||||
		hardSupplyRewardPeriods,
 | 
			
		||||
		hardBorrowRewardPeriods,
 | 
			
		||||
		hardDelegatorRewardPeriods,
 | 
			
		||||
		claimMultipliers,
 | 
			
		||||
		incentiveGS.Params.ClaimEnd,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// Migrate accumulation times
 | 
			
		||||
	var usdxAccumulationTimes v0_15incentive.GenesisAccumulationTimes
 | 
			
		||||
	for _, t := range incentiveGS.USDXAccumulationTimes {
 | 
			
		||||
		newAccumulationTime := v0_15incentive.NewGenesisAccumulationTime(t.CollateralType, t.PreviousAccumulationTime)
 | 
			
		||||
		usdxAccumulationTimes = append(usdxAccumulationTimes, newAccumulationTime)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var hardSupplyAccumulationTimes v0_15incentive.GenesisAccumulationTimes
 | 
			
		||||
	for _, t := range incentiveGS.HardSupplyAccumulationTimes {
 | 
			
		||||
		newAccumulationTime := v0_15incentive.NewGenesisAccumulationTime(t.CollateralType, t.PreviousAccumulationTime)
 | 
			
		||||
		hardSupplyAccumulationTimes = append(hardSupplyAccumulationTimes, newAccumulationTime)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var hardBorrowAccumulationTimes v0_15incentive.GenesisAccumulationTimes
 | 
			
		||||
	for _, t := range incentiveGS.HardBorrowAccumulationTimes {
 | 
			
		||||
		newAccumulationTime := v0_15incentive.NewGenesisAccumulationTime(t.CollateralType, t.PreviousAccumulationTime)
 | 
			
		||||
		hardBorrowAccumulationTimes = append(hardBorrowAccumulationTimes, newAccumulationTime)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var hardDelegatorAccumulationTimes v0_15incentive.GenesisAccumulationTimes
 | 
			
		||||
	for _, t := range incentiveGS.HardDelegatorAccumulationTimes {
 | 
			
		||||
		newAccumulationTime := v0_15incentive.NewGenesisAccumulationTime(t.CollateralType, t.PreviousAccumulationTime)
 | 
			
		||||
		hardDelegatorAccumulationTimes = append(hardDelegatorAccumulationTimes, newAccumulationTime)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Migrate USDX minting claims
 | 
			
		||||
	var usdxMintingClaims v0_15incentive.USDXMintingClaims
 | 
			
		||||
	for _, claim := range incentiveGS.USDXMintingClaims {
 | 
			
		||||
		var rewardIndexes v0_15incentive.RewardIndexes
 | 
			
		||||
		for _, ri := range claim.RewardIndexes {
 | 
			
		||||
			rewardIndex := v0_15incentive.NewRewardIndex(ri.CollateralType, ri.RewardFactor)
 | 
			
		||||
			rewardIndexes = append(rewardIndexes, rewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
		usdxMintingClaim := v0_15incentive.NewUSDXMintingClaim(claim.Owner, claim.Reward, rewardIndexes)
 | 
			
		||||
		usdxMintingClaims = append(usdxMintingClaims, usdxMintingClaim)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Migrate Hard protocol claims (including delegation rewards)
 | 
			
		||||
	var hardClaims v0_15incentive.HardLiquidityProviderClaims
 | 
			
		||||
	for _, claim := range incentiveGS.HardLiquidityProviderClaims {
 | 
			
		||||
		// Migrate supply multi reward indexes
 | 
			
		||||
		var supplyMultiRewardIndexes v0_15incentive.MultiRewardIndexes
 | 
			
		||||
		for _, sri := range claim.SupplyRewardIndexes {
 | 
			
		||||
			var rewardIndexes v0_15incentive.RewardIndexes
 | 
			
		||||
			for _, ri := range sri.RewardIndexes {
 | 
			
		||||
				rewardIndex := v0_15incentive.NewRewardIndex(ri.CollateralType, ri.RewardFactor)
 | 
			
		||||
				rewardIndexes = append(rewardIndexes, rewardIndex)
 | 
			
		||||
			}
 | 
			
		||||
			supplyMultiRewardIndex := v0_15incentive.NewMultiRewardIndex(sri.CollateralType, rewardIndexes)
 | 
			
		||||
			supplyMultiRewardIndexes = append(supplyMultiRewardIndexes, supplyMultiRewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Migrate borrow multi reward indexes
 | 
			
		||||
		var borrowMultiRewardIndexes v0_15incentive.MultiRewardIndexes
 | 
			
		||||
		for _, bri := range claim.BorrowRewardIndexes {
 | 
			
		||||
			var rewardIndexes v0_15incentive.RewardIndexes
 | 
			
		||||
			for _, ri := range bri.RewardIndexes {
 | 
			
		||||
				rewardIndex := v0_15incentive.NewRewardIndex(ri.CollateralType, ri.RewardFactor)
 | 
			
		||||
				rewardIndexes = append(rewardIndexes, rewardIndex)
 | 
			
		||||
			}
 | 
			
		||||
			borrowMultiRewardIndex := v0_15incentive.NewMultiRewardIndex(bri.CollateralType, rewardIndexes)
 | 
			
		||||
			borrowMultiRewardIndexes = append(borrowMultiRewardIndexes, borrowMultiRewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Migrate delegator reward indexes to multi reward indexes under BondDenom
 | 
			
		||||
		var delegatorMultiRewardIndexes v0_15incentive.MultiRewardIndexes
 | 
			
		||||
		var delegatorRewardIndexes v0_15incentive.RewardIndexes
 | 
			
		||||
		for _, ri := range claim.DelegatorRewardIndexes {
 | 
			
		||||
			delegatorRewardIndex := v0_15incentive.NewRewardIndex(ri.CollateralType, ri.RewardFactor)
 | 
			
		||||
			delegatorRewardIndexes = append(delegatorRewardIndexes, delegatorRewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
		delegatorMultiRewardIndex := v0_15incentive.NewMultiRewardIndex(v0_15incentive.BondDenom, delegatorRewardIndexes)
 | 
			
		||||
		delegatorMultiRewardIndexes = append(delegatorMultiRewardIndexes, delegatorMultiRewardIndex)
 | 
			
		||||
 | 
			
		||||
		hardClaim := v0_15incentive.NewHardLiquidityProviderClaim(claim.Owner, claim.Reward,
 | 
			
		||||
			supplyMultiRewardIndexes, borrowMultiRewardIndexes, delegatorMultiRewardIndexes)
 | 
			
		||||
		hardClaims = append(hardClaims, hardClaim)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return v0_15incentive.NewGenesisState(
 | 
			
		||||
		params,
 | 
			
		||||
		usdxAccumulationTimes,
 | 
			
		||||
		hardSupplyAccumulationTimes,
 | 
			
		||||
		hardBorrowAccumulationTimes,
 | 
			
		||||
		hardDelegatorAccumulationTimes,
 | 
			
		||||
		usdxMintingClaims,
 | 
			
		||||
		hardClaims,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,8 @@ import (
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	v0_14committee "github.com/kava-labs/kava/x/committee/legacy/v0_14"
 | 
			
		||||
	v0_15committee "github.com/kava-labs/kava/x/committee/types"
 | 
			
		||||
 | 
			
		||||
	v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14"
 | 
			
		||||
	v0_15incentive "github.com/kava-labs/kava/x/incentive/types"
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -54,3 +55,23 @@ func TestCommittee(t *testing.T) {
 | 
			
		||||
	require.Equal(t, len(oldSPCP.AllowedMarkets), len(newSPCP.AllowedMarkets))
 | 
			
		||||
	require.Equal(t, len(oldSPCP.AllowedMoneyMarkets), len(newSPCP.AllowedMoneyMarkets))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIncentive(t *testing.T) {
 | 
			
		||||
	bz, err := ioutil.ReadFile(filepath.Join("testdata", "kava-7-incentive-state.json"))
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
	var oldIncentiveGenState v0_14incentive.GenesisState
 | 
			
		||||
	cdc := app.MakeCodec()
 | 
			
		||||
	require.NotPanics(t, func() {
 | 
			
		||||
		cdc.MustUnmarshalJSON(bz, &oldIncentiveGenState)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	newGenState := v0_15incentive.GenesisState{}
 | 
			
		||||
	require.NotPanics(t, func() {
 | 
			
		||||
		newGenState = Incentive(oldIncentiveGenState)
 | 
			
		||||
	})
 | 
			
		||||
	err = newGenState.Validate()
 | 
			
		||||
	require.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	require.Equal(t, len(oldIncentiveGenState.USDXMintingClaims), len(newGenState.USDXMintingClaims))
 | 
			
		||||
	require.Equal(t, len(oldIncentiveGenState.HardLiquidityProviderClaims), len(newGenState.HardLiquidityProviderClaims))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								migrate/v0_15/testdata/kava-7-incentive-state.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								migrate/v0_15/testdata/kava-7-incentive-state.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -104,7 +104,7 @@ var (
 | 
			
		||||
	PreviousHardSupplyRewardAccrualTimeKeyPrefix    = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix
 | 
			
		||||
	HardBorrowRewardIndexesKeyPrefix                = types.HardBorrowRewardIndexesKeyPrefix
 | 
			
		||||
	PreviousHardBorrowRewardAccrualTimeKeyPrefix    = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix
 | 
			
		||||
	HardDelegatorRewardFactorKeyPrefix              = types.HardDelegatorRewardFactorKeyPrefix
 | 
			
		||||
	HardDelegatorRewardIndexesKeyPrefix             = types.HardDelegatorRewardIndexesKeyPrefix
 | 
			
		||||
	PreviousHardDelegatorRewardAccrualTimeKeyPrefix = types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix
 | 
			
		||||
	USDXMintingRewardDenom                          = types.USDXMintingRewardDenom
 | 
			
		||||
	HardLiquidityRewardDenom                        = types.HardLiquidityRewardDenom
 | 
			
		||||
 | 
			
		||||
@ -48,8 +48,13 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep
 | 
			
		||||
		k.SetHardBorrowRewardIndexes(ctx, mrp.CollateralType, newRewardIndexes)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, rp := range gs.Params.HardDelegatorRewardPeriods {
 | 
			
		||||
		k.SetHardDelegatorRewardFactor(ctx, rp.CollateralType, sdk.ZeroDec())
 | 
			
		||||
	for _, drp := range gs.Params.HardDelegatorRewardPeriods {
 | 
			
		||||
		newRewardIndexes := types.RewardIndexes{}
 | 
			
		||||
		for _, rc := range drp.RewardsPerSecond {
 | 
			
		||||
			ri := types.NewRewardIndex(rc.Denom, sdk.ZeroDec())
 | 
			
		||||
			newRewardIndexes = append(newRewardIndexes, ri)
 | 
			
		||||
		}
 | 
			
		||||
		k.SetHardDelegatorRewardIndexes(ctx, drp.CollateralType, newRewardIndexes)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	k.SetParams(ctx, gs.Params)
 | 
			
		||||
@ -94,9 +99,11 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for j, ri := range claim.DelegatorRewardIndexes {
 | 
			
		||||
			if ri.RewardFactor != sdk.ZeroDec() {
 | 
			
		||||
				gs.HardLiquidityProviderClaims[i].DelegatorRewardIndexes[j].RewardFactor = sdk.ZeroDec()
 | 
			
		||||
		for j, dri := range claim.DelegatorRewardIndexes {
 | 
			
		||||
			for k, ri := range dri.RewardIndexes {
 | 
			
		||||
				if ri.RewardFactor != sdk.ZeroDec() {
 | 
			
		||||
					gs.HardLiquidityProviderClaims[i].DelegatorRewardIndexes[j].RewardIndexes[k].RewardFactor = sdk.ZeroDec()
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		k.SetHardLiquidityProviderClaim(ctx, claim)
 | 
			
		||||
@ -140,8 +147,10 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
 | 
			
		||||
				claim.SupplyRewardIndexes[i].RewardIndexes[j].RewardFactor = sdk.ZeroDec()
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for i := range claim.DelegatorRewardIndexes {
 | 
			
		||||
			claim.DelegatorRewardIndexes[i].RewardFactor = sdk.ZeroDec()
 | 
			
		||||
		for i, dri := range claim.DelegatorRewardIndexes {
 | 
			
		||||
			for j := range dri.RewardIndexes {
 | 
			
		||||
				claim.DelegatorRewardIndexes[i].RewardIndexes[j].RewardFactor = sdk.ZeroDec()
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		synchronizedHardClaims = append(synchronizedHardClaims, claim)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -64,8 +64,7 @@ func (suite *GenesisTestSuite) SetupTest() {
 | 
			
		||||
			incentive.RewardPeriods{incentive.NewRewardPeriod(true, "bnb-a", suite.genesisTime.Add(-1*oneYear), suite.genesisTime.Add(oneYear), c("ukava", 122354))},
 | 
			
		||||
			incentive.MultiRewardPeriods{incentive.NewMultiRewardPeriod(true, "bnb", suite.genesisTime.Add(-1*oneYear), suite.genesisTime.Add(oneYear), cs(c("hard", 122354)))},
 | 
			
		||||
			incentive.MultiRewardPeriods{incentive.NewMultiRewardPeriod(true, "bnb", suite.genesisTime.Add(-1*oneYear), suite.genesisTime.Add(oneYear), cs(c("hard", 122354)))},
 | 
			
		||||
			incentive.RewardPeriods{incentive.NewRewardPeriod(true, "ukava", suite.genesisTime.Add(-1*oneYear), suite.genesisTime.Add(oneYear), c("hard", 122354))},
 | 
			
		||||
			incentive.Multipliers{incentive.NewMultiplier(incentive.Small, 1, d("0.25")), incentive.NewMultiplier(incentive.Large, 12, d("1.0"))},
 | 
			
		||||
			incentive.MultiRewardPeriods{incentive.NewMultiRewardPeriod(true, "ukava", suite.genesisTime.Add(-1*oneYear), suite.genesisTime.Add(oneYear), cs(c("hard", 122354)))}, incentive.Multipliers{incentive.NewMultiplier(incentive.Small, 1, d("0.25")), incentive.NewMultiplier(incentive.Large, 12, d("1.0"))},
 | 
			
		||||
			suite.genesisTime.Add(5*oneYear),
 | 
			
		||||
		),
 | 
			
		||||
		incentive.DefaultGenesisAccumulationTimes,
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@ func (suite *HandlerTestSuite) SetupTest() {
 | 
			
		||||
			incentive.RewardPeriods{incentive.NewRewardPeriod(true, "bnb-a", time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), time.Date(2024, 12, 15, 14, 0, 0, 0, time.UTC), c("ukava", 122354))},
 | 
			
		||||
			incentive.MultiRewardPeriods{incentive.NewMultiRewardPeriod(true, "bnb-a", time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), time.Date(2024, 12, 15, 14, 0, 0, 0, time.UTC), cs(c("ukava", 122354)))},
 | 
			
		||||
			incentive.MultiRewardPeriods{incentive.NewMultiRewardPeriod(true, "bnb-a", time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), time.Date(2024, 12, 15, 14, 0, 0, 0, time.UTC), cs(c("ukava", 122354)))},
 | 
			
		||||
			incentive.RewardPeriods{incentive.NewRewardPeriod(true, "bnb-a", time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), time.Date(2024, 12, 15, 14, 0, 0, 0, time.UTC), c("ukava", 122354))},
 | 
			
		||||
			incentive.MultiRewardPeriods{incentive.NewMultiRewardPeriod(true, "bnb-a", time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), time.Date(2024, 12, 15, 14, 0, 0, 0, time.UTC), cs(c("ukava", 122354)))},
 | 
			
		||||
			incentive.Multipliers{incentive.NewMultiplier(incentive.MultiplierName("small"), 1, d("0.25")), incentive.NewMultiplier(incentive.MultiplierName("large"), 12, d("1.0"))},
 | 
			
		||||
			time.Date(2025, 12, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
		),
 | 
			
		||||
@ -88,10 +88,9 @@ func (suite *HandlerTestSuite) addHardLiquidityProviderClaim() {
 | 
			
		||||
	err := sk.MintCoins(suite.ctx, kavadist.ModuleName, cs(c("ukava", 1000000000000)))
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	rewardPeriod := types.RewardIndexes{types.NewRewardIndex("bnb-s", sdk.ZeroDec())}
 | 
			
		||||
 | 
			
		||||
	multiRewardIndex := types.NewMultiRewardIndex("bnb-s", rewardPeriod)
 | 
			
		||||
	multiRewardIndexes := types.MultiRewardIndexes{multiRewardIndex}
 | 
			
		||||
	c1 := incentive.NewHardLiquidityProviderClaim(suite.addrs[0], cs(c("ukava", 1000000)), multiRewardIndexes, multiRewardIndexes, rewardPeriod)
 | 
			
		||||
	c1 := incentive.NewHardLiquidityProviderClaim(suite.addrs[0], cs(c("ukava", 1000000)), multiRewardIndexes, multiRewardIndexes, multiRewardIndexes)
 | 
			
		||||
	suite.NotPanics(func() {
 | 
			
		||||
		suite.keeper.SetHardLiquidityProviderClaim(suite.ctx, c1)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
@ -157,7 +157,7 @@ func NewIncentiveGenState(previousAccumTime, endTime time.Time, rewardPeriods ..
 | 
			
		||||
			rewardPeriods,
 | 
			
		||||
			types.MultiRewardPeriods{},
 | 
			
		||||
			types.MultiRewardPeriods{},
 | 
			
		||||
			types.RewardPeriods{},
 | 
			
		||||
			types.MultiRewardPeriods{},
 | 
			
		||||
			incentive.Multipliers{
 | 
			
		||||
				incentive.NewMultiplier(incentive.Small, 1, d("0.25")),
 | 
			
		||||
				incentive.NewMultiplier(incentive.Large, 12, d("1.0")),
 | 
			
		||||
 | 
			
		||||
@ -278,7 +278,7 @@ func (builder IncentiveGenesisBuilder) WithSimpleSupplyRewardPeriod(ctype string
 | 
			
		||||
		rewardsPerSecond,
 | 
			
		||||
	))
 | 
			
		||||
}
 | 
			
		||||
func (builder IncentiveGenesisBuilder) WithInitializedDelegatorRewardPeriod(period types.RewardPeriod) IncentiveGenesisBuilder {
 | 
			
		||||
func (builder IncentiveGenesisBuilder) WithInitializedDelegatorRewardPeriod(period types.MultiRewardPeriod) IncentiveGenesisBuilder {
 | 
			
		||||
	builder.Params.HardDelegatorRewardPeriods = append(builder.Params.HardDelegatorRewardPeriods, period)
 | 
			
		||||
 | 
			
		||||
	accumulationTimeForPeriod := types.NewGenesisAccumulationTime(period.CollateralType, builder.genesisTime)
 | 
			
		||||
@ -286,8 +286,8 @@ func (builder IncentiveGenesisBuilder) WithInitializedDelegatorRewardPeriod(peri
 | 
			
		||||
	return builder
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (builder IncentiveGenesisBuilder) WithSimpleDelegatorRewardPeriod(ctype string, rewardsPerSecond sdk.Coin) IncentiveGenesisBuilder {
 | 
			
		||||
	return builder.WithInitializedDelegatorRewardPeriod(types.NewRewardPeriod(
 | 
			
		||||
func (builder IncentiveGenesisBuilder) WithSimpleDelegatorRewardPeriod(ctype string, rewardsPerSecond sdk.Coins) IncentiveGenesisBuilder {
 | 
			
		||||
	return builder.WithInitializedDelegatorRewardPeriod(types.NewMultiRewardPeriod(
 | 
			
		||||
		true,
 | 
			
		||||
		ctype,
 | 
			
		||||
		builder.genesisTime,
 | 
			
		||||
 | 
			
		||||
@ -273,32 +273,34 @@ func (k Keeper) IterateHardBorrowRewardIndexes(ctx sdk.Context, cb func(denom st
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetHardDelegatorRewardFactor returns the current reward factor for an individual collateral type
 | 
			
		||||
func (k Keeper) GetHardDelegatorRewardFactor(ctx sdk.Context, ctype string) (factor sdk.Dec, found bool) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardFactorKeyPrefix)
 | 
			
		||||
	bz := store.Get([]byte(ctype))
 | 
			
		||||
// GetHardDelegatorRewardIndexes gets the current reward indexes for an individual denom
 | 
			
		||||
func (k Keeper) GetHardDelegatorRewardIndexes(ctx sdk.Context, denom string) (types.RewardIndexes, bool) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix)
 | 
			
		||||
	bz := store.Get([]byte(denom))
 | 
			
		||||
	if bz == nil {
 | 
			
		||||
		return sdk.ZeroDec(), false
 | 
			
		||||
		return types.RewardIndexes{}, false
 | 
			
		||||
	}
 | 
			
		||||
	k.cdc.MustUnmarshalBinaryBare(bz, &factor)
 | 
			
		||||
	return factor, true
 | 
			
		||||
	var rewardIndexes types.RewardIndexes
 | 
			
		||||
	k.cdc.MustUnmarshalBinaryBare(bz, &rewardIndexes)
 | 
			
		||||
	return rewardIndexes, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetHardDelegatorRewardFactor sets the current reward factor for an individual collateral type
 | 
			
		||||
func (k Keeper) SetHardDelegatorRewardFactor(ctx sdk.Context, ctype string, factor sdk.Dec) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardFactorKeyPrefix)
 | 
			
		||||
	store.Set([]byte(ctype), k.cdc.MustMarshalBinaryBare(factor))
 | 
			
		||||
// SetHardDelegatorRewardIndexes sets the current reward indexes for an individual denom
 | 
			
		||||
func (k Keeper) SetHardDelegatorRewardIndexes(ctx sdk.Context, denom string, indexes types.RewardIndexes) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix)
 | 
			
		||||
	bz := k.cdc.MustMarshalBinaryBare(indexes)
 | 
			
		||||
	store.Set([]byte(denom), bz)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IterateHardDelegatorRewardFactors iterates over all Hard delegator reward factor objects in the store and preforms a callback function
 | 
			
		||||
func (k Keeper) IterateHardDelegatorRewardFactors(ctx sdk.Context, cb func(denom string, factor sdk.Dec) (stop bool)) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardFactorKeyPrefix)
 | 
			
		||||
// IterateHardDelegatorRewardIndexes iterates over all Delegator reward index objects in the store and preforms a callback function
 | 
			
		||||
func (k Keeper) IterateHardDelegatorRewardIndexes(ctx sdk.Context, cb func(denom string, indexes types.RewardIndexes) (stop bool)) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.HardDelegatorRewardIndexesKeyPrefix)
 | 
			
		||||
	iterator := sdk.KVStorePrefixIterator(store, []byte{})
 | 
			
		||||
	defer iterator.Close()
 | 
			
		||||
	for ; iterator.Valid(); iterator.Next() {
 | 
			
		||||
		var factor sdk.Dec
 | 
			
		||||
		k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &factor)
 | 
			
		||||
		if cb(string(iterator.Key()), factor) {
 | 
			
		||||
		var indexes types.RewardIndexes
 | 
			
		||||
		k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &indexes)
 | 
			
		||||
		if cb(string(iterator.Key()), indexes) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -54,14 +54,14 @@ func (k Keeper) GetHardBorrowRewardPeriods(ctx sdk.Context, denom string) (types
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetHardDelegatorRewardPeriod returns the reward period with the specified collateral type if it's found in the params
 | 
			
		||||
func (k Keeper) GetHardDelegatorRewardPeriod(ctx sdk.Context, denom string) (types.RewardPeriod, bool) {
 | 
			
		||||
func (k Keeper) GetHardDelegatorRewardPeriods(ctx sdk.Context, denom string) (types.MultiRewardPeriod, bool) {
 | 
			
		||||
	params := k.GetParams(ctx)
 | 
			
		||||
	for _, rp := range params.HardDelegatorRewardPeriods {
 | 
			
		||||
		if rp.CollateralType == denom {
 | 
			
		||||
			return rp, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return types.RewardPeriod{}, false
 | 
			
		||||
	return types.MultiRewardPeriod{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMultiplier returns the multiplier with the specified name if it's found in the params
 | 
			
		||||
 | 
			
		||||
@ -223,9 +223,9 @@ func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]
 | 
			
		||||
		if found {
 | 
			
		||||
			rewardFactor.HardBorrowRewardFactors = hardBorrowRewardIndexes
 | 
			
		||||
		}
 | 
			
		||||
		hardDelegatorRewardFactor, found := k.GetHardDelegatorRewardFactor(ctx, params.Denom)
 | 
			
		||||
		hardDelegatorRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, params.Denom)
 | 
			
		||||
		if found {
 | 
			
		||||
			rewardFactor.HardDelegatorRewardFactor = hardDelegatorRewardFactor
 | 
			
		||||
			rewardFactor.HardDelegatorRewardFactors = hardDelegatorRewardIndexes
 | 
			
		||||
		}
 | 
			
		||||
		rewardFactors = append(rewardFactors, rewardFactor)
 | 
			
		||||
	} else {
 | 
			
		||||
@ -263,12 +263,12 @@ func queryGetRewardFactors(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		// Populate mapping with Hard delegator reward factors
 | 
			
		||||
		k.IterateHardDelegatorRewardFactors(ctx, func(denom string, factor sdk.Dec) (stop bool) {
 | 
			
		||||
		k.IterateHardDelegatorRewardIndexes(ctx, func(denom string, indexes types.RewardIndexes) (stop bool) {
 | 
			
		||||
			rewardFactor, ok := rewardFactorMap[denom]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				rewardFactor = types.RewardFactor{Denom: denom, HardDelegatorRewardFactor: factor}
 | 
			
		||||
				rewardFactor = types.RewardFactor{Denom: denom, HardDelegatorRewardFactors: indexes}
 | 
			
		||||
			} else {
 | 
			
		||||
				rewardFactor.HardDelegatorRewardFactor = factor
 | 
			
		||||
				rewardFactor.HardDelegatorRewardFactors = indexes
 | 
			
		||||
			}
 | 
			
		||||
			rewardFactorMap[denom] = rewardFactor
 | 
			
		||||
			return false
 | 
			
		||||
 | 
			
		||||
@ -9,37 +9,57 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// AccumulateHardDelegatorRewards updates the rewards accumulated for the input reward period
 | 
			
		||||
func (k Keeper) AccumulateHardDelegatorRewards(ctx sdk.Context, rewardPeriod types.RewardPeriod) error {
 | 
			
		||||
	previousAccrualTime, found := k.GetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriod.CollateralType)
 | 
			
		||||
func (k Keeper) AccumulateHardDelegatorRewards(ctx sdk.Context, rewardPeriods types.MultiRewardPeriod) error {
 | 
			
		||||
	previousAccrualTime, found := k.GetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType)
 | 
			
		||||
	if !found {
 | 
			
		||||
		k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriod.CollateralType, ctx.BlockTime())
 | 
			
		||||
		k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime())
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	timeElapsed := CalculateTimeElapsed(rewardPeriod.Start, rewardPeriod.End, ctx.BlockTime(), previousAccrualTime)
 | 
			
		||||
	timeElapsed := CalculateTimeElapsed(rewardPeriods.Start, rewardPeriods.End, ctx.BlockTime(), previousAccrualTime)
 | 
			
		||||
	if timeElapsed.IsZero() {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if rewardPeriod.RewardsPerSecond.Amount.IsZero() {
 | 
			
		||||
		k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriod.CollateralType, ctx.BlockTime())
 | 
			
		||||
	if rewardPeriods.RewardsPerSecond.IsZero() {
 | 
			
		||||
		k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime())
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	totalBonded := k.stakingKeeper.TotalBondedTokens(ctx).ToDec()
 | 
			
		||||
	if totalBonded.IsZero() {
 | 
			
		||||
		k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriod.CollateralType, ctx.BlockTime())
 | 
			
		||||
		k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime())
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	newRewards := timeElapsed.Mul(rewardPeriod.RewardsPerSecond.Amount)
 | 
			
		||||
	rewardFactor := newRewards.ToDec().Quo(totalBonded)
 | 
			
		||||
 | 
			
		||||
	previousRewardFactor, found := k.GetHardDelegatorRewardFactor(ctx, rewardPeriod.CollateralType)
 | 
			
		||||
	previousRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType)
 | 
			
		||||
	if !found {
 | 
			
		||||
		previousRewardFactor = sdk.ZeroDec()
 | 
			
		||||
		for _, rewardCoin := range rewardPeriods.RewardsPerSecond {
 | 
			
		||||
			rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
 | 
			
		||||
			previousRewardIndexes = append(previousRewardIndexes, rewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
		k.SetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, previousRewardIndexes)
 | 
			
		||||
	}
 | 
			
		||||
	newRewardFactor := previousRewardFactor.Add(rewardFactor)
 | 
			
		||||
	k.SetHardDelegatorRewardFactor(ctx, rewardPeriod.CollateralType, newRewardFactor)
 | 
			
		||||
	k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriod.CollateralType, ctx.BlockTime())
 | 
			
		||||
 | 
			
		||||
	newRewardIndexes := previousRewardIndexes
 | 
			
		||||
	for _, rewardCoin := range rewardPeriods.RewardsPerSecond {
 | 
			
		||||
		newRewards := rewardCoin.Amount.ToDec().Mul(timeElapsed.ToDec())
 | 
			
		||||
		previousRewardIndex, found := previousRewardIndexes.GetRewardIndex(rewardCoin.Denom)
 | 
			
		||||
		if !found {
 | 
			
		||||
			previousRewardIndex = types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Calculate new reward factor and update reward index
 | 
			
		||||
		rewardFactor := newRewards.Quo(totalBonded)
 | 
			
		||||
		newRewardFactorValue := previousRewardIndex.RewardFactor.Add(rewardFactor)
 | 
			
		||||
		newRewardIndex := types.NewRewardIndex(rewardCoin.Denom, newRewardFactorValue)
 | 
			
		||||
		i, found := newRewardIndexes.GetFactorIndex(rewardCoin.Denom)
 | 
			
		||||
		if found {
 | 
			
		||||
			newRewardIndexes[i] = newRewardIndex
 | 
			
		||||
		} else {
 | 
			
		||||
			newRewardIndexes = append(newRewardIndexes, newRewardIndex)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	k.SetHardDelegatorRewardIndexes(ctx, rewardPeriods.CollateralType, newRewardIndexes)
 | 
			
		||||
	k.SetPreviousHardDelegatorRewardAccrualTime(ctx, rewardPeriods.CollateralType, ctx.BlockTime())
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -53,13 +73,14 @@ func (k Keeper) InitializeHardDelegatorReward(ctx sdk.Context, delegator sdk.Acc
 | 
			
		||||
		claim, _ = k.GetHardLiquidityProviderClaim(ctx, delegator)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	globalRewardFactor, found := k.GetHardDelegatorRewardFactor(ctx, types.BondDenom)
 | 
			
		||||
	var delegatorRewardIndexes types.MultiRewardIndexes
 | 
			
		||||
	globalRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, types.BondDenom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		// If there's no global delegator reward factor, initialize the claim with a delegator factor of zero.
 | 
			
		||||
		globalRewardFactor = sdk.ZeroDec()
 | 
			
		||||
		globalRewardIndexes = types.RewardIndexes{}
 | 
			
		||||
	}
 | 
			
		||||
	delegatorRewardIndexes = delegatorRewardIndexes.With(types.BondDenom, globalRewardIndexes)
 | 
			
		||||
 | 
			
		||||
	claim.DelegatorRewardIndexes = types.RewardIndexes{types.NewRewardIndex(types.BondDenom, globalRewardFactor)}
 | 
			
		||||
	claim.DelegatorRewardIndexes = delegatorRewardIndexes
 | 
			
		||||
	k.SetHardLiquidityProviderClaim(ctx, claim)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -72,7 +93,7 @@ func (k Keeper) SynchronizeHardDelegatorRewards(ctx sdk.Context, delegator sdk.A
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	globalRewardFactor, found := k.GetHardDelegatorRewardFactor(ctx, types.BondDenom)
 | 
			
		||||
	globalRewardIndexes, found := k.GetHardDelegatorRewardIndexes(ctx, types.BondDenom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		// The global factor is only not found if
 | 
			
		||||
		// - the bond denom has not started accumulating rewards yet (either there is no reward specified in params, or the reward start time hasn't been hit)
 | 
			
		||||
@ -83,27 +104,25 @@ func (k Keeper) SynchronizeHardDelegatorRewards(ctx sdk.Context, delegator sdk.A
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	userRewardFactor, found := claim.DelegatorRewardIndexes.Get(types.BondDenom)
 | 
			
		||||
	userRewardIndexes, found := claim.DelegatorRewardIndexes.Get(types.BondDenom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		// Normally the factor should always be found, as it is added in InitializeHardDelegatorReward when a user delegates.
 | 
			
		||||
		// 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.
 | 
			
		||||
		// So assume the factor is the starting value for any global factor: 0.
 | 
			
		||||
		userRewardFactor = sdk.ZeroDec()
 | 
			
		||||
		userRewardIndexes = types.RewardIndexes{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	totalDelegated := k.GetTotalDelegated(ctx, delegator, valAddr, shouldIncludeValidator)
 | 
			
		||||
 | 
			
		||||
	rewardsEarned, err := k.CalculateSingleReward(userRewardFactor, globalRewardFactor, totalDelegated)
 | 
			
		||||
	rewardsEarned, err := k.CalculateRewards(userRewardIndexes, globalRewardIndexes, totalDelegated)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// Global reward factors should never decrease, as it would lead to a negative update to claim.Rewards.
 | 
			
		||||
		// This panics if a global reward factor decreases or disappears between the old and new indexes.
 | 
			
		||||
		panic(fmt.Sprintf("corrupted global reward indexes found: %v", err))
 | 
			
		||||
	}
 | 
			
		||||
	newRewardsCoin := sdk.NewCoin(types.HardLiquidityRewardDenom, rewardsEarned)
 | 
			
		||||
 | 
			
		||||
	claim.Reward = claim.Reward.Add(newRewardsCoin)
 | 
			
		||||
	claim.DelegatorRewardIndexes = claim.DelegatorRewardIndexes.With(types.BondDenom, globalRewardFactor)
 | 
			
		||||
 | 
			
		||||
	claim.Reward = claim.Reward.Add(rewardsEarned...)
 | 
			
		||||
	claim.DelegatorRewardIndexes = claim.DelegatorRewardIndexes.With(types.BondDenom, globalRewardIndexes)
 | 
			
		||||
	k.SetHardLiquidityProviderClaim(ctx, claim)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,9 +27,10 @@ func TestInitializeHardDelegatorReward(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(InitializeHardDelegatorRewardTests))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *InitializeHardDelegatorRewardTests) storeGlobalDelegatorFactor(rewardIndexes types.RewardIndexes) {
 | 
			
		||||
	factor := rewardIndexes[0]
 | 
			
		||||
	suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, factor.CollateralType, factor.RewardFactor)
 | 
			
		||||
// Hardcoded to use bond denom
 | 
			
		||||
func (suite *InitializeHardDelegatorRewardTests) storeGlobalDelegatorFactor(multiRewardIndexes types.MultiRewardIndexes) {
 | 
			
		||||
	multiRewardIndex, _ := multiRewardIndexes.GetRewardIndex(types.BondDenom)
 | 
			
		||||
	suite.keeper.SetHardDelegatorRewardIndexes(suite.ctx, types.BondDenom, multiRewardIndex.RewardIndexes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *InitializeHardDelegatorRewardTests) TestClaimIndexesAreSetWhenClaimDoesNotExist() {
 | 
			
		||||
@ -70,19 +71,30 @@ func (suite *InitializeHardDelegatorRewardTests) TestClaimIsSyncedAndIndexesAreS
 | 
			
		||||
 | 
			
		||||
	// Set the global factor to a value different to one in claim so
 | 
			
		||||
	// we can detect if it is overwritten.
 | 
			
		||||
	globalIndex := increaseRewardFactors(claim.DelegatorRewardIndexes)
 | 
			
		||||
	suite.storeGlobalDelegatorFactor(globalIndex)
 | 
			
		||||
	rewardIndexes, _ := claim.DelegatorRewardIndexes.Get(types.BondDenom)
 | 
			
		||||
	globalIndexes := increaseRewardFactors(rewardIndexes)
 | 
			
		||||
 | 
			
		||||
	// Update the claim object with the new global factor
 | 
			
		||||
	bondIndex, _ := claim.DelegatorRewardIndexes.GetRewardIndexIndex(types.BondDenom)
 | 
			
		||||
	claim.DelegatorRewardIndexes[bondIndex].RewardIndexes = globalIndexes
 | 
			
		||||
	suite.storeGlobalDelegatorFactor(claim.DelegatorRewardIndexes)
 | 
			
		||||
 | 
			
		||||
	suite.keeper.InitializeHardDelegatorReward(suite.ctx, claim.Owner)
 | 
			
		||||
 | 
			
		||||
	syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner)
 | 
			
		||||
	suite.Equal(globalIndex, syncedClaim.DelegatorRewardIndexes)
 | 
			
		||||
	suite.Equal(globalIndexes, syncedClaim.DelegatorRewardIndexes[bondIndex].RewardIndexes)
 | 
			
		||||
	suite.Truef(syncedClaim.Reward.IsAllGT(claim.Reward), "'%s' not greater than '%s'", syncedClaim.Reward, claim.Reward)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// arbitraryDelegatorRewardIndexes contains only one reward index as there is only every one bond denom
 | 
			
		||||
var arbitraryDelegatorRewardIndexes = types.RewardIndexes{
 | 
			
		||||
	types.NewRewardIndex(types.BondDenom, d("0.2")),
 | 
			
		||||
var arbitraryDelegatorRewardIndexes = types.MultiRewardIndexes{
 | 
			
		||||
	types.NewMultiRewardIndex(
 | 
			
		||||
		types.BondDenom,
 | 
			
		||||
		types.RewardIndexes{
 | 
			
		||||
			types.NewRewardIndex("hard", d("0.2")),
 | 
			
		||||
			types.NewRewardIndex("swp", d("0.2")),
 | 
			
		||||
		},
 | 
			
		||||
	),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type fakeStakingKeeper struct {
 | 
			
		||||
 | 
			
		||||
@ -28,9 +28,9 @@ func TestSynchronizeHardDelegatorReward(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(SynchronizeHardDelegatorRewardTests))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *SynchronizeHardDelegatorRewardTests) storeGlobalDelegatorFactor(rewardIndexes types.RewardIndexes) {
 | 
			
		||||
	factor := rewardIndexes[0]
 | 
			
		||||
	suite.keeper.SetHardDelegatorRewardFactor(suite.ctx, factor.CollateralType, factor.RewardFactor)
 | 
			
		||||
func (suite *SynchronizeHardDelegatorRewardTests) storeGlobalDelegatorFactor(multiRewardIndexes types.MultiRewardIndexes) {
 | 
			
		||||
	multiRewardIndex, _ := multiRewardIndexes.GetRewardIndex(types.BondDenom)
 | 
			
		||||
	suite.keeper.SetHardDelegatorRewardIndexes(suite.ctx, types.BondDenom, multiRewardIndex.RewardIndexes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *SynchronizeHardDelegatorRewardTests) TestClaimIndexesAreUnchangedWhenGlobalFactorUnchanged() {
 | 
			
		||||
@ -68,14 +68,20 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestClaimIndexesAreUpdatedWhen
 | 
			
		||||
	}
 | 
			
		||||
	suite.storeClaim(claim)
 | 
			
		||||
 | 
			
		||||
	globalIndexes := increaseRewardFactors(claim.DelegatorRewardIndexes)
 | 
			
		||||
	suite.storeGlobalDelegatorFactor(globalIndexes)
 | 
			
		||||
	rewardIndexes, _ := claim.DelegatorRewardIndexes.Get(types.BondDenom)
 | 
			
		||||
	globalIndexes := increaseRewardFactors(rewardIndexes)
 | 
			
		||||
 | 
			
		||||
	// Update the claim object with the new global factor
 | 
			
		||||
	bondIndex, _ := claim.DelegatorRewardIndexes.GetRewardIndexIndex(types.BondDenom)
 | 
			
		||||
	claim.DelegatorRewardIndexes[bondIndex].RewardIndexes = globalIndexes
 | 
			
		||||
	suite.storeGlobalDelegatorFactor(claim.DelegatorRewardIndexes)
 | 
			
		||||
 | 
			
		||||
	suite.keeper.SynchronizeHardDelegatorRewards(suite.ctx, claim.Owner, nil, false)
 | 
			
		||||
 | 
			
		||||
	syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner)
 | 
			
		||||
	suite.Equal(globalIndexes, syncedClaim.DelegatorRewardIndexes)
 | 
			
		||||
	suite.Equal(globalIndexes, syncedClaim.DelegatorRewardIndexes[bondIndex].RewardIndexes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsUnchangedWhenGlobalFactorUnchanged() {
 | 
			
		||||
	delegator := arbitraryAddress()
 | 
			
		||||
	validatorAddress := arbitraryValidatorAddress()
 | 
			
		||||
@ -98,9 +104,16 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsUnchangedWhenGloba
 | 
			
		||||
			Owner:  delegator,
 | 
			
		||||
			Reward: arbitraryCoins(),
 | 
			
		||||
		},
 | 
			
		||||
		DelegatorRewardIndexes: types.RewardIndexes{{
 | 
			
		||||
		DelegatorRewardIndexes: types.MultiRewardIndexes{{
 | 
			
		||||
			CollateralType: types.BondDenom,
 | 
			
		||||
			RewardFactor:   d("0.1"),
 | 
			
		||||
			RewardIndexes: types.RewardIndexes{
 | 
			
		||||
				{
 | 
			
		||||
					CollateralType: "hard", RewardFactor: d("0.1"),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					CollateralType: "swp", RewardFactor: d("0.2"),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		}},
 | 
			
		||||
	}
 | 
			
		||||
	suite.storeClaim(claim)
 | 
			
		||||
@ -136,13 +149,20 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRe
 | 
			
		||||
			Owner:  delegator,
 | 
			
		||||
			Reward: arbitraryCoins(),
 | 
			
		||||
		},
 | 
			
		||||
		DelegatorRewardIndexes: types.RewardIndexes{},
 | 
			
		||||
		DelegatorRewardIndexes: types.MultiRewardIndexes{},
 | 
			
		||||
	}
 | 
			
		||||
	suite.storeClaim(claim)
 | 
			
		||||
 | 
			
		||||
	newGlobalIndexes := types.RewardIndexes{{
 | 
			
		||||
	newGlobalIndexes := types.MultiRewardIndexes{{
 | 
			
		||||
		CollateralType: types.BondDenom,
 | 
			
		||||
		RewardFactor:   d("0.1"),
 | 
			
		||||
		RewardIndexes: types.RewardIndexes{
 | 
			
		||||
			{
 | 
			
		||||
				CollateralType: "hard", RewardFactor: d("0.1"),
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				CollateralType: "swp", RewardFactor: d("0.2"),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}}
 | 
			
		||||
	suite.storeGlobalDelegatorFactor(newGlobalIndexes)
 | 
			
		||||
 | 
			
		||||
@ -152,7 +172,10 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenNewRe
 | 
			
		||||
 | 
			
		||||
	suite.Equal(newGlobalIndexes, syncedClaim.DelegatorRewardIndexes)
 | 
			
		||||
	suite.Equal(
 | 
			
		||||
		cs(c(types.HardLiquidityRewardDenom, 100)).Add(claim.Reward...),
 | 
			
		||||
		cs(
 | 
			
		||||
			c(types.HardLiquidityRewardDenom, 100),
 | 
			
		||||
			c("swp", 200),
 | 
			
		||||
		).Add(claim.Reward...),
 | 
			
		||||
		syncedClaim.Reward,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
@ -179,16 +202,33 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGloba
 | 
			
		||||
			Owner:  delegator,
 | 
			
		||||
			Reward: arbitraryCoins(),
 | 
			
		||||
		},
 | 
			
		||||
		DelegatorRewardIndexes: types.RewardIndexes{{
 | 
			
		||||
		DelegatorRewardIndexes: types.MultiRewardIndexes{{
 | 
			
		||||
			CollateralType: types.BondDenom,
 | 
			
		||||
			RewardFactor:   d("0.1"),
 | 
			
		||||
			RewardIndexes: types.RewardIndexes{
 | 
			
		||||
				{
 | 
			
		||||
					CollateralType: "hard", RewardFactor: d("0.1"),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					CollateralType: "swp", RewardFactor: d("0.2"),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		}},
 | 
			
		||||
	}
 | 
			
		||||
	suite.storeClaim(claim)
 | 
			
		||||
 | 
			
		||||
	suite.storeGlobalDelegatorFactor(
 | 
			
		||||
		types.RewardIndexes{
 | 
			
		||||
			types.NewRewardIndex(types.BondDenom, d("0.2")),
 | 
			
		||||
		types.MultiRewardIndexes{
 | 
			
		||||
			types.NewMultiRewardIndex(
 | 
			
		||||
				types.BondDenom,
 | 
			
		||||
				types.RewardIndexes{
 | 
			
		||||
					{
 | 
			
		||||
						CollateralType: "hard", RewardFactor: d("0.2"),
 | 
			
		||||
					},
 | 
			
		||||
					{
 | 
			
		||||
						CollateralType: "swp", RewardFactor: d("0.4"),
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			),
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
@ -197,7 +237,10 @@ func (suite *SynchronizeHardDelegatorRewardTests) TestRewardIsIncreasedWhenGloba
 | 
			
		||||
	syncedClaim, _ := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, claim.Owner)
 | 
			
		||||
 | 
			
		||||
	suite.Equal(
 | 
			
		||||
		cs(c(types.HardLiquidityRewardDenom, 100)).Add(claim.Reward...),
 | 
			
		||||
		cs(
 | 
			
		||||
			c(types.HardLiquidityRewardDenom, 100),
 | 
			
		||||
			c("swp", 200),
 | 
			
		||||
		).Add(claim.Reward...),
 | 
			
		||||
		syncedClaim.Reward,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -66,10 +66,10 @@ func (suite *DelegatorRewardsTestSuite) SetupWithGenState(authBuilder app.AuthGe
 | 
			
		||||
 | 
			
		||||
func (suite *DelegatorRewardsTestSuite) TestAccumulateHardDelegatorRewards() {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		delegation           sdk.Coin
 | 
			
		||||
		rewardsPerSecond     sdk.Coin
 | 
			
		||||
		timeElapsed          int
 | 
			
		||||
		expectedRewardFactor sdk.Dec
 | 
			
		||||
		delegation            sdk.Coin
 | 
			
		||||
		rewardsPerSecond      sdk.Coins
 | 
			
		||||
		timeElapsed           int
 | 
			
		||||
		expectedRewardIndexes types.RewardIndexes
 | 
			
		||||
	}
 | 
			
		||||
	type test struct {
 | 
			
		||||
		name string
 | 
			
		||||
@ -79,28 +79,46 @@ func (suite *DelegatorRewardsTestSuite) TestAccumulateHardDelegatorRewards() {
 | 
			
		||||
		{
 | 
			
		||||
			"7 seconds",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:           c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond:     c("hard", 122354),
 | 
			
		||||
				timeElapsed:          7,
 | 
			
		||||
				expectedRewardFactor: d("0.428239000000000000"),
 | 
			
		||||
				delegation:       c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 122354)),
 | 
			
		||||
				timeElapsed:      7,
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("0.428239000000000000")),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"1 day",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:           c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond:     c("hard", 122354),
 | 
			
		||||
				timeElapsed:          86400,
 | 
			
		||||
				expectedRewardFactor: d("5285.692800000000000000"),
 | 
			
		||||
				delegation:       c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 122354)),
 | 
			
		||||
				timeElapsed:      86400,
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("5285.692800000000000000")),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"0 seconds",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:           c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond:     c("hard", 122354),
 | 
			
		||||
				timeElapsed:          0,
 | 
			
		||||
				expectedRewardFactor: d("0.0"),
 | 
			
		||||
				delegation:       c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 122354)),
 | 
			
		||||
				timeElapsed:      0,
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("0.0")),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"multiple reward coins",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:       c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 122354), c("swp", 567889)),
 | 
			
		||||
				timeElapsed:      7,
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("0.428239000000000000")),
 | 
			
		||||
					types.NewRewardIndex("swp", d("1.987611500000000000")),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
@ -127,24 +145,24 @@ func (suite *DelegatorRewardsTestSuite) TestAccumulateHardDelegatorRewards() {
 | 
			
		||||
			runAtTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * tc.args.timeElapsed))
 | 
			
		||||
			runCtx := suite.ctx.WithBlockTime(runAtTime)
 | 
			
		||||
 | 
			
		||||
			rewardPeriod, found := suite.keeper.GetHardDelegatorRewardPeriod(runCtx, tc.args.delegation.Denom)
 | 
			
		||||
			rewardPeriods, found := suite.keeper.GetHardDelegatorRewardPeriods(runCtx, tc.args.delegation.Denom)
 | 
			
		||||
			suite.Require().True(found)
 | 
			
		||||
			err = suite.keeper.AccumulateHardDelegatorRewards(runCtx, rewardPeriod)
 | 
			
		||||
			err = suite.keeper.AccumulateHardDelegatorRewards(runCtx, rewardPeriods)
 | 
			
		||||
			suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
			rewardFactor, _ := suite.keeper.GetHardDelegatorRewardFactor(runCtx, tc.args.delegation.Denom)
 | 
			
		||||
			suite.Require().Equal(tc.args.expectedRewardFactor, rewardFactor)
 | 
			
		||||
			rewardIndexes, _ := suite.keeper.GetHardDelegatorRewardIndexes(runCtx, tc.args.delegation.Denom)
 | 
			
		||||
			suite.Require().Equal(tc.args.expectedRewardIndexes, rewardIndexes)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		delegation           sdk.Coin
 | 
			
		||||
		rewardsPerSecond     sdk.Coin
 | 
			
		||||
		blockTimes           []int
 | 
			
		||||
		expectedRewardFactor sdk.Dec
 | 
			
		||||
		expectedRewards      sdk.Coins
 | 
			
		||||
		delegation            sdk.Coin
 | 
			
		||||
		rewardsPerSecond      sdk.Coins
 | 
			
		||||
		blockTimes            []int
 | 
			
		||||
		expectedRewardIndexes types.RewardIndexes
 | 
			
		||||
		expectedRewards       sdk.Coins
 | 
			
		||||
	}
 | 
			
		||||
	type test struct {
 | 
			
		||||
		name string
 | 
			
		||||
@ -155,31 +173,50 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
 | 
			
		||||
		{
 | 
			
		||||
			"10 blocks",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:           c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond:     c("hard", 122354),
 | 
			
		||||
				blockTimes:           []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
			
		||||
				expectedRewardFactor: d("6.117700000000000000"),
 | 
			
		||||
				expectedRewards:      cs(c("hard", 6117700)),
 | 
			
		||||
				delegation:       c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 122354)),
 | 
			
		||||
				blockTimes:       []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("6.117700000000000000")),
 | 
			
		||||
				},
 | 
			
		||||
				expectedRewards: cs(c("hard", 6117700)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"10 blocks - long block time",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:           c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond:     c("hard", 122354),
 | 
			
		||||
				blockTimes:           []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
 | 
			
		||||
				expectedRewardFactor: d("52856.928000000000000000"),
 | 
			
		||||
				expectedRewards:      cs(c("hard", 52856928000)),
 | 
			
		||||
				delegation:       c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 122354)),
 | 
			
		||||
				blockTimes:       []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("52856.928000000000000000")),
 | 
			
		||||
				},
 | 
			
		||||
				expectedRewards: cs(c("hard", 52856928000)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"delegator reward index updated when reward is zero",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:           c("ukava", 1),
 | 
			
		||||
				rewardsPerSecond:     c("hard", 1),
 | 
			
		||||
				blockTimes:           []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
			
		||||
				expectedRewardFactor: d("0.000099999900000100"),
 | 
			
		||||
				expectedRewards:      nil,
 | 
			
		||||
				delegation:       c("ukava", 1),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 1)),
 | 
			
		||||
				blockTimes:       []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("0.000099999900000100")),
 | 
			
		||||
				},
 | 
			
		||||
				expectedRewards: nil,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"multiple reward coins",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:       c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 122354), c("swp", 56789)),
 | 
			
		||||
				blockTimes:       []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("6.117700000000000000")),
 | 
			
		||||
					types.NewRewardIndex("swp", d("2.839450000000000000")),
 | 
			
		||||
				},
 | 
			
		||||
				expectedRewards: cs(c("hard", 6117700), c("swp", 2839450)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
@ -215,7 +252,9 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
 | 
			
		||||
			// Check that Staking hooks initialized a HardLiquidityProviderClaim
 | 
			
		||||
			claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
 | 
			
		||||
			suite.Require().True(found)
 | 
			
		||||
			suite.Require().Equal(sdk.ZeroDec(), claim.DelegatorRewardIndexes[0].RewardFactor)
 | 
			
		||||
			for _, rewardIndex := range claim.DelegatorRewardIndexes[0].RewardIndexes {
 | 
			
		||||
				suite.Require().Equal(sdk.ZeroDec(), rewardIndex.RewardFactor)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Run accumulator at several intervals
 | 
			
		||||
			var timeElapsed int
 | 
			
		||||
@ -226,10 +265,10 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
 | 
			
		||||
				previousBlockTime = updatedBlockTime
 | 
			
		||||
				blockCtx := suite.ctx.WithBlockTime(updatedBlockTime)
 | 
			
		||||
 | 
			
		||||
				rewardPeriod, found := suite.keeper.GetHardDelegatorRewardPeriod(blockCtx, tc.args.delegation.Denom)
 | 
			
		||||
				rewardPeriods, found := suite.keeper.GetHardDelegatorRewardPeriods(blockCtx, tc.args.delegation.Denom)
 | 
			
		||||
				suite.Require().True(found)
 | 
			
		||||
 | 
			
		||||
				err := suite.keeper.AccumulateHardDelegatorRewards(blockCtx, rewardPeriod)
 | 
			
		||||
				err := suite.keeper.AccumulateHardDelegatorRewards(blockCtx, rewardPeriods)
 | 
			
		||||
				suite.Require().NoError(err)
 | 
			
		||||
			}
 | 
			
		||||
			updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed))
 | 
			
		||||
@ -241,12 +280,17 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			// Check that reward factor and claim have been updated as expected
 | 
			
		||||
			rewardFactor, _ := suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, tc.args.delegation.Denom)
 | 
			
		||||
			suite.Require().Equal(tc.args.expectedRewardFactor, rewardFactor)
 | 
			
		||||
			rewardIndexes, _ := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, tc.args.delegation.Denom)
 | 
			
		||||
			for i, rewardPerSecond := range tc.args.rewardsPerSecond {
 | 
			
		||||
				rewardFactor, _ := rewardIndexes.Get(rewardPerSecond.Denom)
 | 
			
		||||
				suite.Require().Equal(tc.args.expectedRewardIndexes[i].RewardFactor, rewardFactor)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			claim, found = suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
 | 
			
		||||
			suite.Require().True(found)
 | 
			
		||||
			suite.Require().Equal(tc.args.expectedRewardFactor, claim.DelegatorRewardIndexes[0].RewardFactor)
 | 
			
		||||
			for i, delegatorRewardIndex := range claim.DelegatorRewardIndexes[0].RewardIndexes {
 | 
			
		||||
				suite.Require().Equal(tc.args.expectedRewardIndexes[i].RewardFactor, delegatorRewardIndex.RewardFactor)
 | 
			
		||||
			}
 | 
			
		||||
			suite.Require().Equal(tc.args.expectedRewards, claim.Reward)
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
@ -255,7 +299,7 @@ func (suite *DelegatorRewardsTestSuite) TestSynchronizeHardDelegatorReward() {
 | 
			
		||||
func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchronization() {
 | 
			
		||||
	type args struct {
 | 
			
		||||
		delegation            sdk.Coin
 | 
			
		||||
		rewardsPerSecond      sdk.Coin
 | 
			
		||||
		rewardsPerSecond      sdk.Coins
 | 
			
		||||
		blockTimes            []int
 | 
			
		||||
		expectedRewardIndexes types.RewardIndexes
 | 
			
		||||
		expectedRewards       sdk.Coins
 | 
			
		||||
@ -270,9 +314,9 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni
 | 
			
		||||
			"10 blocks",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:            c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond:      c("hard", 122354),
 | 
			
		||||
				rewardsPerSecond:      cs(c("hard", 122354)),
 | 
			
		||||
				blockTimes:            []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("ukava", d("6.117700000000000000"))}, // Here the reward index stores data differently than inside a MultiRewardIndex
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("6.117700000000000000"))},
 | 
			
		||||
				expectedRewards:       cs(c("hard", 6117700)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
@ -280,12 +324,25 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni
 | 
			
		||||
			"10 blocks - long block time",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:            c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond:      c("hard", 122354),
 | 
			
		||||
				rewardsPerSecond:      cs(c("hard", 122354)),
 | 
			
		||||
				blockTimes:            []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("ukava", d("52856.928000000000000000"))},
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{types.NewRewardIndex("hard", d("52856.928000000000000000"))},
 | 
			
		||||
				expectedRewards:       cs(c("hard", 52856928000)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"multiple rewards coins",
 | 
			
		||||
			args{
 | 
			
		||||
				delegation:       c("ukava", 1_000_000),
 | 
			
		||||
				rewardsPerSecond: cs(c("hard", 122354), c("swp", 56789)),
 | 
			
		||||
				blockTimes:       []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
			
		||||
				expectedRewardIndexes: types.RewardIndexes{
 | 
			
		||||
					types.NewRewardIndex("hard", d("6.117700000000000000")),
 | 
			
		||||
					types.NewRewardIndex("swp", d("2.839450000000000000")),
 | 
			
		||||
				},
 | 
			
		||||
				expectedRewards: cs(c("hard", 6117700), c("swp", 2839450)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
@ -311,7 +368,9 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni
 | 
			
		||||
			// Check that Staking hooks initialized a HardLiquidityProviderClaim
 | 
			
		||||
			claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
 | 
			
		||||
			suite.Require().True(found)
 | 
			
		||||
			suite.Require().Equal(sdk.ZeroDec(), claim.DelegatorRewardIndexes[0].RewardFactor)
 | 
			
		||||
			for _, rewardIndex := range claim.DelegatorRewardIndexes[0].RewardIndexes {
 | 
			
		||||
				suite.Require().Equal(sdk.ZeroDec(), rewardIndex.RewardFactor)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Run accumulator at several intervals
 | 
			
		||||
			var timeElapsed int
 | 
			
		||||
@ -323,9 +382,9 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni
 | 
			
		||||
				blockCtx := suite.ctx.WithBlockTime(updatedBlockTime)
 | 
			
		||||
 | 
			
		||||
				// Accumulate hard delegator rewards
 | 
			
		||||
				rewardPeriod, found := suite.keeper.GetHardDelegatorRewardPeriod(blockCtx, tc.args.delegation.Denom)
 | 
			
		||||
				rewardPeriods, found := suite.keeper.GetHardDelegatorRewardPeriods(blockCtx, tc.args.delegation.Denom)
 | 
			
		||||
				suite.Require().True(found)
 | 
			
		||||
				err := suite.keeper.AccumulateHardDelegatorRewards(blockCtx, rewardPeriod)
 | 
			
		||||
				err := suite.keeper.AccumulateHardDelegatorRewards(blockCtx, rewardPeriods)
 | 
			
		||||
				suite.Require().NoError(err)
 | 
			
		||||
			}
 | 
			
		||||
			updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed))
 | 
			
		||||
@ -333,11 +392,12 @@ func (suite *DelegatorRewardsTestSuite) TestSimulateHardDelegatorRewardSynchroni
 | 
			
		||||
 | 
			
		||||
			// Check that the synced claim held in memory has properly simulated syncing
 | 
			
		||||
			syncedClaim := suite.keeper.SimulateHardSynchronization(suite.ctx, claim)
 | 
			
		||||
			for _, 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
 | 
			
		||||
				rewardIndex, found := syncedClaim.DelegatorRewardIndexes.GetRewardIndex(expectedRewardIndex.CollateralType)
 | 
			
		||||
				multiRewardIndex, found := syncedClaim.DelegatorRewardIndexes.Get(types.BondDenom)
 | 
			
		||||
				suite.Require().True(found)
 | 
			
		||||
				suite.Require().Equal(expectedRewardIndex, rewardIndex)
 | 
			
		||||
				suite.Require().Equal(expectedRewardIndex, multiRewardIndex[i])
 | 
			
		||||
 | 
			
		||||
				// Check that the user's claim holds the expected amount of reward coins
 | 
			
		||||
				suite.Require().Equal(
 | 
			
		||||
@ -395,7 +455,7 @@ func (suite *DelegatorRewardsTestSuite) TestUnbondingValidatorSyncsClaim() {
 | 
			
		||||
		WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[1]), cs(c("ukava", 1e9))).
 | 
			
		||||
		WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[2]), cs(c("ukava", 1e9)))
 | 
			
		||||
 | 
			
		||||
	rewardsPerSecond := c("hard", 122354)
 | 
			
		||||
	rewardsPerSecond := cs(c("hard", 122354))
 | 
			
		||||
	bondDenom := "ukava"
 | 
			
		||||
 | 
			
		||||
	incentBuilder := NewIncentiveGenesisBuilder().
 | 
			
		||||
@ -446,14 +506,16 @@ func (suite *DelegatorRewardsTestSuite) TestUnbondingValidatorSyncsClaim() {
 | 
			
		||||
	claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
 | 
			
		||||
	globalIndex, found := suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, bondDenom)
 | 
			
		||||
	rewardIndexes, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	globalIndex, found := rewardIndexes.Get(rewardsPerSecond[0].Denom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(globalIndex, claimIndex.RewardFactor)
 | 
			
		||||
	suite.Require().Equal(globalIndex, claimIndex.RewardIndexes[0].RewardFactor)
 | 
			
		||||
 | 
			
		||||
	suite.Require().Equal(
 | 
			
		||||
		cs(c(rewardsPerSecond.Denom, 76471)),
 | 
			
		||||
		cs(c(rewardsPerSecond[0].Denom, 76471)),
 | 
			
		||||
		claim.Reward,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
@ -471,9 +533,11 @@ func (suite *DelegatorRewardsTestSuite) TestUnbondingValidatorSyncsClaim() {
 | 
			
		||||
	// claim index has been updated to latest global value
 | 
			
		||||
	laterClaimIndex, found := laterClaim.DelegatorRewardIndexes.GetRewardIndex(bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	globalIndex, found = suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, bondDenom)
 | 
			
		||||
	rewardIndexes, found = suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(globalIndex, laterClaimIndex.RewardFactor)
 | 
			
		||||
	globalIndex, found = rewardIndexes.Get(rewardsPerSecond[0].Denom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(globalIndex, laterClaimIndex.RewardIndexes[0].RewardFactor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// given a user has a delegation to an unbonded validator, when the validator becomes bonded, the user starts accumulating rewards
 | 
			
		||||
@ -485,7 +549,7 @@ func (suite *DelegatorRewardsTestSuite) TestBondingValidatorSyncsClaim() {
 | 
			
		||||
		WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[1]), cs(c("ukava", 1e9))).
 | 
			
		||||
		WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[2]), cs(c("ukava", 1e9)))
 | 
			
		||||
 | 
			
		||||
	rewardsPerSecond := c("hard", 122354)
 | 
			
		||||
	rewardsPerSecond := cs(c("hard", 122354))
 | 
			
		||||
	bondDenom := "ukava"
 | 
			
		||||
 | 
			
		||||
	incentBuilder := NewIncentiveGenesisBuilder().
 | 
			
		||||
@ -536,11 +600,13 @@ func (suite *DelegatorRewardsTestSuite) TestBondingValidatorSyncsClaim() {
 | 
			
		||||
	claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
 | 
			
		||||
	globalIndex, found := suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, bondDenom)
 | 
			
		||||
	rewardIndexes, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	globalIndex, found := rewardIndexes.Get(rewardsPerSecond[0].Denom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(globalIndex, claimIndex.RewardFactor)
 | 
			
		||||
	suite.Require().Equal(globalIndex, claimIndex.RewardIndexes[0].RewardFactor)
 | 
			
		||||
 | 
			
		||||
	suite.Require().Equal(
 | 
			
		||||
		sdk.Coins(nil),
 | 
			
		||||
@ -561,9 +627,11 @@ func (suite *DelegatorRewardsTestSuite) TestBondingValidatorSyncsClaim() {
 | 
			
		||||
	// claim index has been updated to latest global value
 | 
			
		||||
	laterClaimIndex, found := laterClaim.DelegatorRewardIndexes.GetRewardIndex(bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	globalIndex, found = suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, bondDenom)
 | 
			
		||||
	rewardIndexes, found = suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(globalIndex, laterClaimIndex.RewardFactor)
 | 
			
		||||
	globalIndex, found = rewardIndexes.Get(rewardsPerSecond[0].Denom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(globalIndex, laterClaimIndex.RewardIndexes[0].RewardFactor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// If a validator is slashed delegators should have their claims synced
 | 
			
		||||
@ -573,7 +641,7 @@ func (suite *DelegatorRewardsTestSuite) TestSlashingValidatorSyncsClaim() {
 | 
			
		||||
		WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9))).
 | 
			
		||||
		WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[1]), cs(c("ukava", 1e9)))
 | 
			
		||||
 | 
			
		||||
	rewardsPerSecond := c("hard", 122354)
 | 
			
		||||
	rewardsPerSecond := cs(c("hard", 122354))
 | 
			
		||||
	bondDenom := "ukava"
 | 
			
		||||
 | 
			
		||||
	incentBuilder := NewIncentiveGenesisBuilder().
 | 
			
		||||
@ -608,11 +676,11 @@ func (suite *DelegatorRewardsTestSuite) TestSlashingValidatorSyncsClaim() {
 | 
			
		||||
	// Check that claim has been created with synced reward index but no reward coins
 | 
			
		||||
	initialClaim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
 | 
			
		||||
	suite.True(found)
 | 
			
		||||
	initialGlobalIndex, found := suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, bondDenom)
 | 
			
		||||
	initialGlobalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom)
 | 
			
		||||
	suite.True(found)
 | 
			
		||||
	initialClaimIndex, found := initialClaim.DelegatorRewardIndexes.GetRewardIndex(bondDenom)
 | 
			
		||||
	suite.True(found)
 | 
			
		||||
	suite.Require().Equal(initialGlobalIndex, initialClaimIndex.RewardFactor)
 | 
			
		||||
	suite.Require().Equal(initialGlobalIndex, initialClaimIndex.RewardIndexes)
 | 
			
		||||
	suite.True(initialClaim.Reward.Empty()) // Initial claim should not have any rewards
 | 
			
		||||
 | 
			
		||||
	// Start a new block to accumulate some delegation rewards for the user.
 | 
			
		||||
@ -631,20 +699,20 @@ func (suite *DelegatorRewardsTestSuite) TestSlashingValidatorSyncsClaim() {
 | 
			
		||||
	// Check that the user's claim has been synced. ie rewards added, index updated
 | 
			
		||||
	claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	globalIndex, found := suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, bondDenom)
 | 
			
		||||
	globalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(globalIndex, claimIndex.RewardFactor)
 | 
			
		||||
	suite.Require().Equal(globalIndex, claimIndex.RewardIndexes)
 | 
			
		||||
 | 
			
		||||
	// Check that rewards were added
 | 
			
		||||
	suite.Require().Equal(
 | 
			
		||||
		cs(c(rewardsPerSecond.Denom, 58264)),
 | 
			
		||||
		cs(c(rewardsPerSecond[0].Denom, 58264)),
 | 
			
		||||
		claim.Reward,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// Check that reward factor increased from initial value
 | 
			
		||||
	suite.True(claimIndex.RewardFactor.GT(initialClaimIndex.RewardFactor))
 | 
			
		||||
	suite.True(claimIndex.RewardIndexes[0].RewardFactor.GT(initialClaimIndex.RewardIndexes[0].RewardFactor))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Given a delegation to a bonded validator, when a user redelegates everything to another (bonded) validator, the user's claim is synced
 | 
			
		||||
@ -654,7 +722,7 @@ func (suite *DelegatorRewardsTestSuite) TestRedelegationSyncsClaim() {
 | 
			
		||||
		WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[0]), cs(c("ukava", 1e9))).
 | 
			
		||||
		WithSimpleAccount(sdk.AccAddress(suite.validatorAddrs[1]), cs(c("ukava", 1e9)))
 | 
			
		||||
 | 
			
		||||
	rewardsPerSecond := c("hard", 122354)
 | 
			
		||||
	rewardsPerSecond := cs(c("hard", 122354))
 | 
			
		||||
	bondDenom := "ukava"
 | 
			
		||||
 | 
			
		||||
	incentBuilder := NewIncentiveGenesisBuilder().
 | 
			
		||||
@ -689,13 +757,13 @@ func (suite *DelegatorRewardsTestSuite) TestRedelegationSyncsClaim() {
 | 
			
		||||
	claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[0])
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
 | 
			
		||||
	globalIndex, found := suite.keeper.GetHardDelegatorRewardFactor(suite.ctx, bondDenom)
 | 
			
		||||
	globalIndex, found := suite.keeper.GetHardDelegatorRewardIndexes(suite.ctx, bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	claimIndex, found := claim.DelegatorRewardIndexes.GetRewardIndex(bondDenom)
 | 
			
		||||
	suite.Require().True(found)
 | 
			
		||||
	suite.Require().Equal(globalIndex, claimIndex.RewardFactor)
 | 
			
		||||
	suite.Require().Equal(globalIndex, claimIndex.RewardIndexes)
 | 
			
		||||
	suite.Require().Equal(
 | 
			
		||||
		cs(c(rewardsPerSecond.Denom, 76471)),
 | 
			
		||||
		cs(c(rewardsPerSecond[0].Denom, 76471)),
 | 
			
		||||
		claim.Reward,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -300,58 +300,56 @@ func (k Keeper) SimulateHardSynchronization(ctx sdk.Context, claim types.HardLiq
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 3. Simulate Hard delegator rewards
 | 
			
		||||
	delagatorFactor, found := k.GetHardDelegatorRewardFactor(ctx, types.BondDenom)
 | 
			
		||||
	if !found {
 | 
			
		||||
		return claim
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	delegatorIndex, hasDelegatorRewardIndex := claim.HasDelegatorRewardIndex(types.BondDenom)
 | 
			
		||||
	if !hasDelegatorRewardIndex {
 | 
			
		||||
		return claim
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	userRewardFactor := claim.DelegatorRewardIndexes[delegatorIndex].RewardFactor
 | 
			
		||||
	rewardsAccumulatedFactor := delagatorFactor.Sub(userRewardFactor)
 | 
			
		||||
	if rewardsAccumulatedFactor.IsZero() {
 | 
			
		||||
		return claim
 | 
			
		||||
	}
 | 
			
		||||
	claim.DelegatorRewardIndexes[delegatorIndex].RewardFactor = delagatorFactor
 | 
			
		||||
 | 
			
		||||
	totalDelegated := sdk.ZeroDec()
 | 
			
		||||
 | 
			
		||||
	delegations := k.stakingKeeper.GetDelegatorDelegations(ctx, claim.GetOwner(), 200)
 | 
			
		||||
	for _, delegation := range delegations {
 | 
			
		||||
		validator, found := k.stakingKeeper.GetValidator(ctx, delegation.GetValidatorAddr())
 | 
			
		||||
		if !found {
 | 
			
		||||
	// 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
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Delegators don't accumulate rewards if their validator is unbonded/slashed
 | 
			
		||||
		if validator.GetStatus() != sdk.Bonded {
 | 
			
		||||
		userRewardIndexes, foundUserRewardIndexes := claim.DelegatorRewardIndexes.GetRewardIndex(ri.CollateralType)
 | 
			
		||||
		if !foundUserRewardIndexes {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if validator.GetTokens().IsZero() {
 | 
			
		||||
		userRewardIndexIndex, foundUserRewardIndexIndex := claim.DelegatorRewardIndexes.GetRewardIndexIndex(ri.CollateralType)
 | 
			
		||||
		if !foundUserRewardIndexIndex {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		delegatedTokens := validator.TokensFromShares(delegation.GetShares())
 | 
			
		||||
		if delegatedTokens.IsZero() || delegatedTokens.IsNegative() {
 | 
			
		||||
			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)
 | 
			
		||||
		}
 | 
			
		||||
		totalDelegated = totalDelegated.Add(delegatedTokens)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rewardsEarned := rewardsAccumulatedFactor.Mul(totalDelegated).RoundInt()
 | 
			
		||||
	if rewardsEarned.IsZero() || rewardsEarned.IsNegative() {
 | 
			
		||||
		return claim
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add rewards to delegator's hard claim
 | 
			
		||||
	newRewardsCoin := sdk.NewCoin(types.HardLiquidityRewardDenom, rewardsEarned)
 | 
			
		||||
	claim.Reward = claim.Reward.Add(newRewardsCoin)
 | 
			
		||||
 | 
			
		||||
	return claim
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										965
									
								
								x/incentive/legacy/v0_14/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										965
									
								
								x/incentive/legacy/v0_14/types.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,965 @@
 | 
			
		||||
package v0_14
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/x/params"
 | 
			
		||||
 | 
			
		||||
	tmtime "github.com/tendermint/tendermint/types/time"
 | 
			
		||||
 | 
			
		||||
	cdptypes "github.com/kava-labs/kava/x/cdp/types"
 | 
			
		||||
	kavadistTypes "github.com/kava-labs/kava/x/kavadist/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Valid reward multipliers
 | 
			
		||||
const (
 | 
			
		||||
	Small                          MultiplierName = "small"
 | 
			
		||||
	Medium                         MultiplierName = "medium"
 | 
			
		||||
	Large                          MultiplierName = "large"
 | 
			
		||||
	USDXMintingClaimType                          = "usdx_minting"
 | 
			
		||||
	HardLiquidityProviderClaimType                = "hard_liquidity_provider"
 | 
			
		||||
	BondDenom                                     = "ukava"
 | 
			
		||||
	ModuleName                                    = "incentive"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Parameter keys and default values
 | 
			
		||||
var (
 | 
			
		||||
	KeyUSDXMintingRewardPeriods     = []byte("USDXMintingRewardPeriods")
 | 
			
		||||
	KeyHardSupplyRewardPeriods      = []byte("HardSupplyRewardPeriods")
 | 
			
		||||
	KeyHardBorrowRewardPeriods      = []byte("HardBorrowRewardPeriods")
 | 
			
		||||
	KeyHardDelegatorRewardPeriods   = []byte("HardDelegatorRewardPeriods")
 | 
			
		||||
	KeyClaimEnd                     = []byte("ClaimEnd")
 | 
			
		||||
	KeyMultipliers                  = []byte("ClaimMultipliers")
 | 
			
		||||
	DefaultActive                   = false
 | 
			
		||||
	DefaultRewardPeriods            = RewardPeriods{}
 | 
			
		||||
	DefaultMultiRewardPeriods       = MultiRewardPeriods{}
 | 
			
		||||
	DefaultMultipliers              = Multipliers{}
 | 
			
		||||
	DefaultUSDXClaims               = USDXMintingClaims{}
 | 
			
		||||
	DefaultHardClaims               = HardLiquidityProviderClaims{}
 | 
			
		||||
	DefaultGenesisAccumulationTimes = GenesisAccumulationTimes{}
 | 
			
		||||
	DefaultClaimEnd                 = tmtime.Canonical(time.Unix(1, 0))
 | 
			
		||||
	GovDenom                        = cdptypes.DefaultGovDenom
 | 
			
		||||
	PrincipalDenom                  = "usdx"
 | 
			
		||||
	IncentiveMacc                   = kavadistTypes.ModuleName
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GenesisState is the state that must be provided at genesis.
 | 
			
		||||
type GenesisState struct {
 | 
			
		||||
	Params                         Params                      `json:"params" yaml:"params"`
 | 
			
		||||
	USDXAccumulationTimes          GenesisAccumulationTimes    `json:"usdx_accumulation_times" yaml:"usdx_accumulation_times"`
 | 
			
		||||
	HardSupplyAccumulationTimes    GenesisAccumulationTimes    `json:"hard_supply_accumulation_times" yaml:"hard_supply_accumulation_times"`
 | 
			
		||||
	HardBorrowAccumulationTimes    GenesisAccumulationTimes    `json:"hard_borrow_accumulation_times" yaml:"hard_borrow_accumulation_times"`
 | 
			
		||||
	HardDelegatorAccumulationTimes GenesisAccumulationTimes    `json:"hard_delegator_accumulation_times" yaml:"hard_delegator_accumulation_times"`
 | 
			
		||||
	USDXMintingClaims              USDXMintingClaims           `json:"usdx_minting_claims" yaml:"usdx_minting_claims"`
 | 
			
		||||
	HardLiquidityProviderClaims    HardLiquidityProviderClaims `json:"hard_liquidity_provider_claims" yaml:"hard_liquidity_provider_claims"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewGenesisState returns a new genesis state
 | 
			
		||||
func NewGenesisState(params Params, usdxAccumTimes, hardSupplyAccumTimes, hardBorrowAccumTimes, hardDelegatorAccumTimes GenesisAccumulationTimes, c USDXMintingClaims, hc HardLiquidityProviderClaims) GenesisState {
 | 
			
		||||
	return GenesisState{
 | 
			
		||||
		Params:                         params,
 | 
			
		||||
		USDXAccumulationTimes:          usdxAccumTimes,
 | 
			
		||||
		HardSupplyAccumulationTimes:    hardSupplyAccumTimes,
 | 
			
		||||
		HardBorrowAccumulationTimes:    hardBorrowAccumTimes,
 | 
			
		||||
		HardDelegatorAccumulationTimes: hardDelegatorAccumTimes,
 | 
			
		||||
		USDXMintingClaims:              c,
 | 
			
		||||
		HardLiquidityProviderClaims:    hc,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultGenesisState returns a default genesis state
 | 
			
		||||
func DefaultGenesisState() GenesisState {
 | 
			
		||||
	return GenesisState{
 | 
			
		||||
		Params:                         DefaultParams(),
 | 
			
		||||
		USDXAccumulationTimes:          GenesisAccumulationTimes{},
 | 
			
		||||
		HardSupplyAccumulationTimes:    GenesisAccumulationTimes{},
 | 
			
		||||
		HardBorrowAccumulationTimes:    GenesisAccumulationTimes{},
 | 
			
		||||
		HardDelegatorAccumulationTimes: GenesisAccumulationTimes{},
 | 
			
		||||
		USDXMintingClaims:              DefaultUSDXClaims,
 | 
			
		||||
		HardLiquidityProviderClaims:    DefaultHardClaims,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate performs basic validation of genesis data returning an
 | 
			
		||||
// error for any failed validation criteria.
 | 
			
		||||
func (gs GenesisState) Validate() error {
 | 
			
		||||
	if err := gs.Params.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := gs.USDXAccumulationTimes.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := gs.HardSupplyAccumulationTimes.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := gs.HardBorrowAccumulationTimes.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := gs.HardDelegatorAccumulationTimes.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := gs.HardLiquidityProviderClaims.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return gs.USDXMintingClaims.Validate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenesisAccumulationTime stores the previous reward distribution time and its corresponding collateral type
 | 
			
		||||
type GenesisAccumulationTime struct {
 | 
			
		||||
	CollateralType           string    `json:"collateral_type" yaml:"collateral_type"`
 | 
			
		||||
	PreviousAccumulationTime time.Time `json:"previous_accumulation_time" yaml:"previous_accumulation_time"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewGenesisAccumulationTime returns a new GenesisAccumulationTime
 | 
			
		||||
func NewGenesisAccumulationTime(ctype string, prevTime time.Time) GenesisAccumulationTime {
 | 
			
		||||
	return GenesisAccumulationTime{
 | 
			
		||||
		CollateralType:           ctype,
 | 
			
		||||
		PreviousAccumulationTime: prevTime,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenesisAccumulationTimes slice of GenesisAccumulationTime
 | 
			
		||||
type GenesisAccumulationTimes []GenesisAccumulationTime
 | 
			
		||||
 | 
			
		||||
// Validate performs validation of GenesisAccumulationTimes
 | 
			
		||||
func (gats GenesisAccumulationTimes) Validate() error {
 | 
			
		||||
	for _, gat := range gats {
 | 
			
		||||
		if err := gat.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate performs validation of GenesisAccumulationTime
 | 
			
		||||
func (gat GenesisAccumulationTime) Validate() error {
 | 
			
		||||
	if len(gat.CollateralType) == 0 {
 | 
			
		||||
		return fmt.Errorf("genesis accumulation time's collateral type must be defined")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Params governance parameters for the incentive module
 | 
			
		||||
type Params struct {
 | 
			
		||||
	USDXMintingRewardPeriods   RewardPeriods      `json:"usdx_minting_reward_periods" yaml:"usdx_minting_reward_periods"`
 | 
			
		||||
	HardSupplyRewardPeriods    MultiRewardPeriods `json:"hard_supply_reward_periods" yaml:"hard_supply_reward_periods"`
 | 
			
		||||
	HardBorrowRewardPeriods    MultiRewardPeriods `json:"hard_borrow_reward_periods" yaml:"hard_borrow_reward_periods"`
 | 
			
		||||
	HardDelegatorRewardPeriods RewardPeriods      `json:"hard_delegator_reward_periods" yaml:"hard_delegator_reward_periods"`
 | 
			
		||||
	ClaimMultipliers           Multipliers        `json:"claim_multipliers" yaml:"claim_multipliers"`
 | 
			
		||||
	ClaimEnd                   time.Time          `json:"claim_end" yaml:"claim_end"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewParams returns a new params object
 | 
			
		||||
func NewParams(usdxMinting RewardPeriods, hardSupply, hardBorrow MultiRewardPeriods,
 | 
			
		||||
	hardDelegator RewardPeriods, multipliers Multipliers, claimEnd time.Time) Params {
 | 
			
		||||
	return Params{
 | 
			
		||||
		USDXMintingRewardPeriods:   usdxMinting,
 | 
			
		||||
		HardSupplyRewardPeriods:    hardSupply,
 | 
			
		||||
		HardBorrowRewardPeriods:    hardBorrow,
 | 
			
		||||
		HardDelegatorRewardPeriods: hardDelegator,
 | 
			
		||||
		ClaimMultipliers:           multipliers,
 | 
			
		||||
		ClaimEnd:                   claimEnd,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DefaultParams returns default params for incentive module
 | 
			
		||||
func DefaultParams() Params {
 | 
			
		||||
	return NewParams(DefaultRewardPeriods, DefaultMultiRewardPeriods,
 | 
			
		||||
		DefaultMultiRewardPeriods, DefaultRewardPeriods, DefaultMultipliers, DefaultClaimEnd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (p Params) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Params:
 | 
			
		||||
	USDX Minting Reward Periods: %s
 | 
			
		||||
	Hard Supply Reward Periods: %s
 | 
			
		||||
	Hard Borrow Reward Periods: %s
 | 
			
		||||
	Hard Delegator Reward Periods: %s
 | 
			
		||||
	Claim Multipliers :%s
 | 
			
		||||
	Claim End Time: %s
 | 
			
		||||
	`, p.USDXMintingRewardPeriods, p.HardSupplyRewardPeriods, p.HardBorrowRewardPeriods,
 | 
			
		||||
		p.HardDelegatorRewardPeriods, p.ClaimMultipliers, p.ClaimEnd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParamKeyTable Key declaration for parameters
 | 
			
		||||
func ParamKeyTable() params.KeyTable {
 | 
			
		||||
	return params.NewKeyTable().RegisterParamSet(&Params{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParamSetPairs implements the ParamSet interface and returns all the key/value pairs
 | 
			
		||||
func (p *Params) ParamSetPairs() params.ParamSetPairs {
 | 
			
		||||
	return params.ParamSetPairs{
 | 
			
		||||
		params.NewParamSetPair(KeyUSDXMintingRewardPeriods, &p.USDXMintingRewardPeriods, validateRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyHardSupplyRewardPeriods, &p.HardSupplyRewardPeriods, validateMultiRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyHardBorrowRewardPeriods, &p.HardBorrowRewardPeriods, validateMultiRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyHardDelegatorRewardPeriods, &p.HardDelegatorRewardPeriods, validateRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyClaimEnd, &p.ClaimEnd, validateClaimEndParam),
 | 
			
		||||
		params.NewParamSetPair(KeyMultipliers, &p.ClaimMultipliers, validateMultipliersParam),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate checks that the parameters have valid values.
 | 
			
		||||
func (p Params) Validate() error {
 | 
			
		||||
 | 
			
		||||
	if err := validateMultipliersParam(p.ClaimMultipliers); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := validateRewardPeriodsParam(p.USDXMintingRewardPeriods); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := validateMultiRewardPeriodsParam(p.HardSupplyRewardPeriods); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := validateMultiRewardPeriodsParam(p.HardBorrowRewardPeriods); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return validateRewardPeriodsParam(p.HardDelegatorRewardPeriods)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func validateRewardPeriodsParam(i interface{}) error {
 | 
			
		||||
	rewards, ok := i.(RewardPeriods)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return fmt.Errorf("invalid parameter type: %T", i)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return rewards.Validate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func validateMultiRewardPeriodsParam(i interface{}) error {
 | 
			
		||||
	rewards, ok := i.(MultiRewardPeriods)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return fmt.Errorf("invalid parameter type: %T", i)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return rewards.Validate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func validateMultipliersParam(i interface{}) error {
 | 
			
		||||
	multipliers, ok := i.(Multipliers)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return fmt.Errorf("invalid parameter type: %T", i)
 | 
			
		||||
	}
 | 
			
		||||
	return multipliers.Validate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func validateClaimEndParam(i interface{}) error {
 | 
			
		||||
	endTime, ok := i.(time.Time)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return fmt.Errorf("invalid parameter type: %T", i)
 | 
			
		||||
	}
 | 
			
		||||
	if endTime.Unix() <= 0 {
 | 
			
		||||
		return fmt.Errorf("end time should not be zero")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RewardPeriod stores the state of an ongoing reward
 | 
			
		||||
type RewardPeriod struct {
 | 
			
		||||
	Active           bool      `json:"active" yaml:"active"`
 | 
			
		||||
	CollateralType   string    `json:"collateral_type" yaml:"collateral_type"`
 | 
			
		||||
	Start            time.Time `json:"start" yaml:"start"`
 | 
			
		||||
	End              time.Time `json:"end" yaml:"end"`
 | 
			
		||||
	RewardsPerSecond sdk.Coin  `json:"rewards_per_second" yaml:"rewards_per_second"` // per second reward payouts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (rp RewardPeriod) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Reward Period:
 | 
			
		||||
	Collateral Type: %s,
 | 
			
		||||
	Start: %s,
 | 
			
		||||
	End: %s,
 | 
			
		||||
	Rewards Per Second: %s,
 | 
			
		||||
	Active %t,
 | 
			
		||||
	`, rp.CollateralType, rp.Start, rp.End, rp.RewardsPerSecond, rp.Active)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewRewardPeriod returns a new RewardPeriod
 | 
			
		||||
func NewRewardPeriod(active bool, collateralType string, start time.Time, end time.Time, reward sdk.Coin) RewardPeriod {
 | 
			
		||||
	return RewardPeriod{
 | 
			
		||||
		Active:           active,
 | 
			
		||||
		CollateralType:   collateralType,
 | 
			
		||||
		Start:            start,
 | 
			
		||||
		End:              end,
 | 
			
		||||
		RewardsPerSecond: reward,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate performs a basic check of a RewardPeriod fields.
 | 
			
		||||
func (rp RewardPeriod) Validate() error {
 | 
			
		||||
	if rp.Start.Unix() <= 0 {
 | 
			
		||||
		return errors.New("reward period start time cannot be 0")
 | 
			
		||||
	}
 | 
			
		||||
	if rp.End.Unix() <= 0 {
 | 
			
		||||
		return errors.New("reward period end time cannot be 0")
 | 
			
		||||
	}
 | 
			
		||||
	if rp.Start.After(rp.End) {
 | 
			
		||||
		return fmt.Errorf("end period time %s cannot be before start time %s", rp.End, rp.Start)
 | 
			
		||||
	}
 | 
			
		||||
	if !rp.RewardsPerSecond.IsValid() {
 | 
			
		||||
		return fmt.Errorf("invalid reward amount: %s", rp.RewardsPerSecond)
 | 
			
		||||
	}
 | 
			
		||||
	if strings.TrimSpace(rp.CollateralType) == "" {
 | 
			
		||||
		return fmt.Errorf("reward period collateral type cannot be blank: %s", rp)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RewardPeriods array of RewardPeriod
 | 
			
		||||
type RewardPeriods []RewardPeriod
 | 
			
		||||
 | 
			
		||||
// Validate checks if all the RewardPeriods are valid and there are no duplicated
 | 
			
		||||
// entries.
 | 
			
		||||
func (rps RewardPeriods) Validate() error {
 | 
			
		||||
	seenPeriods := make(map[string]bool)
 | 
			
		||||
	for _, rp := range rps {
 | 
			
		||||
		if seenPeriods[rp.CollateralType] {
 | 
			
		||||
			return fmt.Errorf("duplicated reward period with collateral type %s", rp.CollateralType)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := rp.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		seenPeriods[rp.CollateralType] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Multiplier amount the claim rewards get increased by, along with how long the claim rewards are locked
 | 
			
		||||
type Multiplier struct {
 | 
			
		||||
	Name         MultiplierName `json:"name" yaml:"name"`
 | 
			
		||||
	MonthsLockup int64          `json:"months_lockup" yaml:"months_lockup"`
 | 
			
		||||
	Factor       sdk.Dec        `json:"factor" yaml:"factor"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMultiplier returns a new Multiplier
 | 
			
		||||
func NewMultiplier(name MultiplierName, lockup int64, factor sdk.Dec) Multiplier {
 | 
			
		||||
	return Multiplier{
 | 
			
		||||
		Name:         name,
 | 
			
		||||
		MonthsLockup: lockup,
 | 
			
		||||
		Factor:       factor,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate multiplier param
 | 
			
		||||
func (m Multiplier) Validate() error {
 | 
			
		||||
	if err := m.Name.IsValid(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if m.MonthsLockup < 0 {
 | 
			
		||||
		return fmt.Errorf("expected non-negative lockup, got %d", m.MonthsLockup)
 | 
			
		||||
	}
 | 
			
		||||
	if m.Factor.IsNegative() {
 | 
			
		||||
		return fmt.Errorf("expected non-negative factor, got %s", m.Factor.String())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (m Multiplier) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Claim Multiplier:
 | 
			
		||||
	Name: %s
 | 
			
		||||
	Months Lockup %d
 | 
			
		||||
	Factor %s
 | 
			
		||||
	`, m.Name, m.MonthsLockup, m.Factor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Multipliers slice of Multiplier
 | 
			
		||||
type Multipliers []Multiplier
 | 
			
		||||
 | 
			
		||||
// Validate validates each multiplier
 | 
			
		||||
func (ms Multipliers) Validate() error {
 | 
			
		||||
	for _, m := range ms {
 | 
			
		||||
		if err := m.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (ms Multipliers) String() string {
 | 
			
		||||
	out := "Claim Multipliers\n"
 | 
			
		||||
	for _, s := range ms {
 | 
			
		||||
		out += fmt.Sprintf("%s\n", s)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MultiplierName name for valid multiplier
 | 
			
		||||
type MultiplierName string
 | 
			
		||||
 | 
			
		||||
// IsValid checks if the input is one of the expected strings
 | 
			
		||||
func (mn MultiplierName) IsValid() error {
 | 
			
		||||
	switch mn {
 | 
			
		||||
	case Small, Medium, Large:
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Errorf("invalid multiplier name: %s", mn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Claim is an interface for handling common claim actions
 | 
			
		||||
type Claim interface {
 | 
			
		||||
	GetOwner() sdk.AccAddress
 | 
			
		||||
	GetReward() sdk.Coin
 | 
			
		||||
	GetType() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Claims is a slice of Claim
 | 
			
		||||
type Claims []Claim
 | 
			
		||||
 | 
			
		||||
// BaseClaim is a common type shared by all Claims
 | 
			
		||||
type BaseClaim struct {
 | 
			
		||||
	Owner  sdk.AccAddress `json:"owner" yaml:"owner"`
 | 
			
		||||
	Reward sdk.Coin       `json:"reward" yaml:"reward"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetOwner is a getter for Claim Owner
 | 
			
		||||
func (c BaseClaim) GetOwner() sdk.AccAddress { return c.Owner }
 | 
			
		||||
 | 
			
		||||
// GetReward is a getter for Claim Reward
 | 
			
		||||
func (c BaseClaim) GetReward() sdk.Coin { return c.Reward }
 | 
			
		||||
 | 
			
		||||
// GetType returns the claim type, used to identify auctions in event attributes
 | 
			
		||||
func (c BaseClaim) GetType() string { return "base" }
 | 
			
		||||
 | 
			
		||||
// Validate performs a basic check of a BaseClaim fields
 | 
			
		||||
func (c BaseClaim) Validate() error {
 | 
			
		||||
	if c.Owner.Empty() {
 | 
			
		||||
		return errors.New("claim owner cannot be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if !c.Reward.IsValid() {
 | 
			
		||||
		return fmt.Errorf("invalid reward amount: %s", c.Reward)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (c BaseClaim) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Claim:
 | 
			
		||||
	Owner: %s,
 | 
			
		||||
	Reward: %s,
 | 
			
		||||
	`, c.Owner, c.Reward)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BaseMultiClaim is a common type shared by all Claims with multiple reward denoms
 | 
			
		||||
type BaseMultiClaim struct {
 | 
			
		||||
	Owner  sdk.AccAddress `json:"owner" yaml:"owner"`
 | 
			
		||||
	Reward sdk.Coins      `json:"reward" yaml:"reward"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetOwner is a getter for Claim Owner
 | 
			
		||||
func (c BaseMultiClaim) GetOwner() sdk.AccAddress { return c.Owner }
 | 
			
		||||
 | 
			
		||||
// GetReward is a getter for Claim Reward
 | 
			
		||||
func (c BaseMultiClaim) GetReward() sdk.Coins { return c.Reward }
 | 
			
		||||
 | 
			
		||||
// GetType returns the claim type, used to identify auctions in event attributes
 | 
			
		||||
func (c BaseMultiClaim) GetType() string { return "base" }
 | 
			
		||||
 | 
			
		||||
// Validate performs a basic check of a BaseClaim fields
 | 
			
		||||
func (c BaseMultiClaim) Validate() error {
 | 
			
		||||
	if c.Owner.Empty() {
 | 
			
		||||
		return errors.New("claim owner cannot be empty")
 | 
			
		||||
	}
 | 
			
		||||
	if !c.Reward.IsValid() {
 | 
			
		||||
		return fmt.Errorf("invalid reward amount: %s", c.Reward)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (c BaseMultiClaim) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Claim:
 | 
			
		||||
	Owner: %s,
 | 
			
		||||
	Reward: %s,
 | 
			
		||||
	`, c.Owner, c.Reward)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -------------- Custom Claim Types --------------
 | 
			
		||||
 | 
			
		||||
// USDXMintingClaim is for USDX minting rewards
 | 
			
		||||
type USDXMintingClaim struct {
 | 
			
		||||
	BaseClaim     `json:"base_claim" yaml:"base_claim"`
 | 
			
		||||
	RewardIndexes RewardIndexes `json:"reward_indexes" yaml:"reward_indexes"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewUSDXMintingClaim returns a new USDXMintingClaim
 | 
			
		||||
func NewUSDXMintingClaim(owner sdk.AccAddress, reward sdk.Coin, rewardIndexes RewardIndexes) USDXMintingClaim {
 | 
			
		||||
	return USDXMintingClaim{
 | 
			
		||||
		BaseClaim: BaseClaim{
 | 
			
		||||
			Owner:  owner,
 | 
			
		||||
			Reward: reward,
 | 
			
		||||
		},
 | 
			
		||||
		RewardIndexes: rewardIndexes,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetType returns the claim's type
 | 
			
		||||
func (c USDXMintingClaim) GetType() string { return USDXMintingClaimType }
 | 
			
		||||
 | 
			
		||||
// GetReward returns the claim's reward coin
 | 
			
		||||
func (c USDXMintingClaim) GetReward() sdk.Coin { return c.Reward }
 | 
			
		||||
 | 
			
		||||
// GetOwner returns the claim's owner
 | 
			
		||||
func (c USDXMintingClaim) GetOwner() sdk.AccAddress { return c.Owner }
 | 
			
		||||
 | 
			
		||||
// Validate performs a basic check of a Claim fields
 | 
			
		||||
func (c USDXMintingClaim) Validate() error {
 | 
			
		||||
	if err := c.RewardIndexes.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.BaseClaim.Validate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (c USDXMintingClaim) String() string {
 | 
			
		||||
	return fmt.Sprintf(`%s
 | 
			
		||||
	Reward Indexes: %s,
 | 
			
		||||
	`, c.BaseClaim, c.RewardIndexes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasRewardIndex check if a claim has a reward index for the input collateral type
 | 
			
		||||
func (c USDXMintingClaim) HasRewardIndex(collateralType string) (int64, bool) {
 | 
			
		||||
	for index, ri := range c.RewardIndexes {
 | 
			
		||||
		if ri.CollateralType == collateralType {
 | 
			
		||||
			return int64(index), true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// USDXMintingClaims slice of USDXMintingClaim
 | 
			
		||||
type USDXMintingClaims []USDXMintingClaim
 | 
			
		||||
 | 
			
		||||
// Validate checks if all the claims are valid and there are no duplicated
 | 
			
		||||
// entries.
 | 
			
		||||
func (cs USDXMintingClaims) Validate() error {
 | 
			
		||||
	for _, c := range cs {
 | 
			
		||||
		if err := c.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HardLiquidityProviderClaim stores the hard liquidity provider rewards that can be claimed by owner
 | 
			
		||||
type HardLiquidityProviderClaim struct {
 | 
			
		||||
	BaseMultiClaim         `json:"base_claim" yaml:"base_claim"`
 | 
			
		||||
	SupplyRewardIndexes    MultiRewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"`
 | 
			
		||||
	BorrowRewardIndexes    MultiRewardIndexes `json:"borrow_reward_indexes" yaml:"borrow_reward_indexes"`
 | 
			
		||||
	DelegatorRewardIndexes RewardIndexes      `json:"delegator_reward_indexes" yaml:"delegator_reward_indexes"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewHardLiquidityProviderClaim returns a new HardLiquidityProviderClaim
 | 
			
		||||
func NewHardLiquidityProviderClaim(owner sdk.AccAddress, rewards sdk.Coins, supplyRewardIndexes,
 | 
			
		||||
	borrowRewardIndexes MultiRewardIndexes, delegatorRewardIndexes RewardIndexes) HardLiquidityProviderClaim {
 | 
			
		||||
	return HardLiquidityProviderClaim{
 | 
			
		||||
		BaseMultiClaim: BaseMultiClaim{
 | 
			
		||||
			Owner:  owner,
 | 
			
		||||
			Reward: rewards,
 | 
			
		||||
		},
 | 
			
		||||
		SupplyRewardIndexes:    supplyRewardIndexes,
 | 
			
		||||
		BorrowRewardIndexes:    borrowRewardIndexes,
 | 
			
		||||
		DelegatorRewardIndexes: delegatorRewardIndexes,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetType returns the claim's type
 | 
			
		||||
func (c HardLiquidityProviderClaim) GetType() string { return HardLiquidityProviderClaimType }
 | 
			
		||||
 | 
			
		||||
// GetReward returns the claim's reward coin
 | 
			
		||||
func (c HardLiquidityProviderClaim) GetReward() sdk.Coins { return c.Reward }
 | 
			
		||||
 | 
			
		||||
// GetOwner returns the claim's owner
 | 
			
		||||
func (c HardLiquidityProviderClaim) GetOwner() sdk.AccAddress { return c.Owner }
 | 
			
		||||
 | 
			
		||||
// Validate performs a basic check of a HardLiquidityProviderClaim fields
 | 
			
		||||
func (c HardLiquidityProviderClaim) Validate() error {
 | 
			
		||||
	if err := c.SupplyRewardIndexes.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := c.BorrowRewardIndexes.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := c.DelegatorRewardIndexes.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.BaseMultiClaim.Validate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (c HardLiquidityProviderClaim) String() string {
 | 
			
		||||
	return fmt.Sprintf(`%s
 | 
			
		||||
	Supply Reward Indexes: %s,
 | 
			
		||||
	Borrow Reward Indexes: %s,
 | 
			
		||||
	Delegator Reward Indexes: %s,
 | 
			
		||||
	`, c.BaseMultiClaim, c.SupplyRewardIndexes, c.BorrowRewardIndexes, c.DelegatorRewardIndexes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasSupplyRewardIndex check if a claim has a supply reward index for the input collateral type
 | 
			
		||||
func (c HardLiquidityProviderClaim) HasSupplyRewardIndex(denom string) (int64, bool) {
 | 
			
		||||
	for index, ri := range c.SupplyRewardIndexes {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return int64(index), true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasBorrowRewardIndex check if a claim has a borrow reward index for the input collateral type
 | 
			
		||||
func (c HardLiquidityProviderClaim) HasBorrowRewardIndex(denom string) (int64, bool) {
 | 
			
		||||
	for index, ri := range c.BorrowRewardIndexes {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return int64(index), true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasDelegatorRewardIndex check if a claim has a delegator reward index for the input collateral type
 | 
			
		||||
func (c HardLiquidityProviderClaim) HasDelegatorRewardIndex(collateralType string) (int64, bool) {
 | 
			
		||||
	for index, ri := range c.DelegatorRewardIndexes {
 | 
			
		||||
		if ri.CollateralType == collateralType {
 | 
			
		||||
			return int64(index), true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HardLiquidityProviderClaims slice of HardLiquidityProviderClaim
 | 
			
		||||
type HardLiquidityProviderClaims []HardLiquidityProviderClaim
 | 
			
		||||
 | 
			
		||||
// Validate checks if all the claims are valid and there are no duplicated
 | 
			
		||||
// entries.
 | 
			
		||||
func (cs HardLiquidityProviderClaims) Validate() error {
 | 
			
		||||
	for _, c := range cs {
 | 
			
		||||
		if err := c.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ---------------------- Reward periods are used by the params ----------------------
 | 
			
		||||
 | 
			
		||||
// MultiRewardPeriod supports multiple reward types
 | 
			
		||||
type MultiRewardPeriod struct {
 | 
			
		||||
	Active           bool      `json:"active" yaml:"active"`
 | 
			
		||||
	CollateralType   string    `json:"collateral_type" yaml:"collateral_type"`
 | 
			
		||||
	Start            time.Time `json:"start" yaml:"start"`
 | 
			
		||||
	End              time.Time `json:"end" yaml:"end"`
 | 
			
		||||
	RewardsPerSecond sdk.Coins `json:"rewards_per_second" yaml:"rewards_per_second"` // per second reward payouts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
func (mrp MultiRewardPeriod) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Reward Period:
 | 
			
		||||
	Collateral Type: %s,
 | 
			
		||||
	Start: %s,
 | 
			
		||||
	End: %s,
 | 
			
		||||
	Rewards Per Second: %s,
 | 
			
		||||
	Active %t,
 | 
			
		||||
	`, mrp.CollateralType, mrp.Start, mrp.End, mrp.RewardsPerSecond, mrp.Active)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMultiRewardPeriod returns a new MultiRewardPeriod
 | 
			
		||||
func NewMultiRewardPeriod(active bool, collateralType string, start time.Time, end time.Time, reward sdk.Coins) MultiRewardPeriod {
 | 
			
		||||
	return MultiRewardPeriod{
 | 
			
		||||
		Active:           active,
 | 
			
		||||
		CollateralType:   collateralType,
 | 
			
		||||
		Start:            start,
 | 
			
		||||
		End:              end,
 | 
			
		||||
		RewardsPerSecond: reward,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate performs a basic check of a MultiRewardPeriod.
 | 
			
		||||
func (mrp MultiRewardPeriod) Validate() error {
 | 
			
		||||
	if mrp.Start.IsZero() {
 | 
			
		||||
		return errors.New("reward period start time cannot be 0")
 | 
			
		||||
	}
 | 
			
		||||
	if mrp.End.IsZero() {
 | 
			
		||||
		return errors.New("reward period end time cannot be 0")
 | 
			
		||||
	}
 | 
			
		||||
	if mrp.Start.After(mrp.End) {
 | 
			
		||||
		return fmt.Errorf("end period time %s cannot be before start time %s", mrp.End, mrp.Start)
 | 
			
		||||
	}
 | 
			
		||||
	if !mrp.RewardsPerSecond.IsValid() {
 | 
			
		||||
		return fmt.Errorf("invalid reward amount: %s", mrp.RewardsPerSecond)
 | 
			
		||||
	}
 | 
			
		||||
	if strings.TrimSpace(mrp.CollateralType) == "" {
 | 
			
		||||
		return fmt.Errorf("reward period collateral type cannot be blank: %s", mrp)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MultiRewardPeriods array of MultiRewardPeriod
 | 
			
		||||
type MultiRewardPeriods []MultiRewardPeriod
 | 
			
		||||
 | 
			
		||||
// GetMultiRewardPeriod fetches a MultiRewardPeriod from an array of MultiRewardPeriods by its denom
 | 
			
		||||
func (mrps MultiRewardPeriods) GetMultiRewardPeriod(denom string) (MultiRewardPeriod, bool) {
 | 
			
		||||
	for _, rp := range mrps {
 | 
			
		||||
		if rp.CollateralType == denom {
 | 
			
		||||
			return rp, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return MultiRewardPeriod{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetMultiRewardPeriodIndex returns the index of a MultiRewardPeriod inside array MultiRewardPeriods
 | 
			
		||||
func (mrps MultiRewardPeriods) GetMultiRewardPeriodIndex(denom string) (int, bool) {
 | 
			
		||||
	for i, rp := range mrps {
 | 
			
		||||
		if rp.CollateralType == denom {
 | 
			
		||||
			return i, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate checks if all the RewardPeriods are valid and there are no duplicated
 | 
			
		||||
// entries.
 | 
			
		||||
func (mrps MultiRewardPeriods) Validate() error {
 | 
			
		||||
	seenPeriods := make(map[string]bool)
 | 
			
		||||
	for _, rp := range mrps {
 | 
			
		||||
		if seenPeriods[rp.CollateralType] {
 | 
			
		||||
			return fmt.Errorf("duplicated reward period with collateral type %s", rp.CollateralType)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := rp.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		seenPeriods[rp.CollateralType] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ---------------------- Reward indexes are used internally in the store ----------------------
 | 
			
		||||
 | 
			
		||||
// RewardIndex stores reward accumulation information
 | 
			
		||||
type RewardIndex struct {
 | 
			
		||||
	CollateralType string  `json:"collateral_type" yaml:"collateral_type"`
 | 
			
		||||
	RewardFactor   sdk.Dec `json:"reward_factor" yaml:"reward_factor"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewRewardIndex returns a new RewardIndex
 | 
			
		||||
func NewRewardIndex(collateralType string, factor sdk.Dec) RewardIndex {
 | 
			
		||||
	return RewardIndex{
 | 
			
		||||
		CollateralType: collateralType,
 | 
			
		||||
		RewardFactor:   factor,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ri RewardIndex) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Collateral Type: %s, RewardFactor: %s`, ri.CollateralType, ri.RewardFactor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate validates reward index
 | 
			
		||||
func (ri RewardIndex) Validate() error {
 | 
			
		||||
	if ri.RewardFactor.IsNegative() {
 | 
			
		||||
		return fmt.Errorf("reward factor value should be positive, is %s for %s", ri.RewardFactor, ri.CollateralType)
 | 
			
		||||
	}
 | 
			
		||||
	if strings.TrimSpace(ri.CollateralType) == "" {
 | 
			
		||||
		return fmt.Errorf("collateral type should not be empty")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RewardIndexes slice of RewardIndex
 | 
			
		||||
type RewardIndexes []RewardIndex
 | 
			
		||||
 | 
			
		||||
// GetRewardIndex fetches a RewardIndex by its denom
 | 
			
		||||
func (ris RewardIndexes) GetRewardIndex(denom string) (RewardIndex, bool) {
 | 
			
		||||
	for _, ri := range ris {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return ri, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return RewardIndex{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get fetches a RewardFactor by it's denom
 | 
			
		||||
func (ris RewardIndexes) Get(denom string) (sdk.Dec, bool) {
 | 
			
		||||
	for _, ri := range ris {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return ri.RewardFactor, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return sdk.Dec{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// With returns a copy of the indexes with a new reward factor added
 | 
			
		||||
func (ris RewardIndexes) With(denom string, factor sdk.Dec) RewardIndexes {
 | 
			
		||||
	newIndexes := make(RewardIndexes, len(ris))
 | 
			
		||||
	copy(newIndexes, ris)
 | 
			
		||||
 | 
			
		||||
	for i, ri := range newIndexes {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			newIndexes[i].RewardFactor = factor
 | 
			
		||||
			return newIndexes
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return append(newIndexes, NewRewardIndex(denom, factor))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFactorIndex gets the index of a specific reward index inside the array by its index
 | 
			
		||||
func (ris RewardIndexes) GetFactorIndex(denom string) (int, bool) {
 | 
			
		||||
	for i, ri := range ris {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return i, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate validation for reward indexes
 | 
			
		||||
func (ris RewardIndexes) Validate() error {
 | 
			
		||||
	for _, ri := range ris {
 | 
			
		||||
		if err := ri.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MultiRewardIndex stores reward accumulation information on multiple reward types
 | 
			
		||||
type MultiRewardIndex struct {
 | 
			
		||||
	CollateralType string        `json:"collateral_type" yaml:"collateral_type"`
 | 
			
		||||
	RewardIndexes  RewardIndexes `json:"reward_indexes" yaml:"reward_indexes"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMultiRewardIndex returns a new MultiRewardIndex
 | 
			
		||||
func NewMultiRewardIndex(collateralType string, indexes RewardIndexes) MultiRewardIndex {
 | 
			
		||||
	return MultiRewardIndex{
 | 
			
		||||
		CollateralType: collateralType,
 | 
			
		||||
		RewardIndexes:  indexes,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFactorIndex gets the index of a specific reward index inside the array by its index
 | 
			
		||||
func (mri MultiRewardIndex) GetFactorIndex(denom string) (int, bool) {
 | 
			
		||||
	for i, ri := range mri.RewardIndexes {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return i, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (mri MultiRewardIndex) String() string {
 | 
			
		||||
	return fmt.Sprintf(`Collateral Type: %s, Reward Indexes: %s`, mri.CollateralType, mri.RewardIndexes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate validates multi-reward index
 | 
			
		||||
func (mri MultiRewardIndex) Validate() error {
 | 
			
		||||
	for _, rf := range mri.RewardIndexes {
 | 
			
		||||
		if rf.RewardFactor.IsNegative() {
 | 
			
		||||
			return fmt.Errorf("reward index's factor value cannot be negative: %s", rf)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if strings.TrimSpace(mri.CollateralType) == "" {
 | 
			
		||||
		return fmt.Errorf("collateral type should not be empty")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MultiRewardIndexes slice of MultiRewardIndex
 | 
			
		||||
type MultiRewardIndexes []MultiRewardIndex
 | 
			
		||||
 | 
			
		||||
// GetRewardIndex fetches a RewardIndex from a MultiRewardIndex by its denom
 | 
			
		||||
func (mris MultiRewardIndexes) GetRewardIndex(denom string) (MultiRewardIndex, bool) {
 | 
			
		||||
	for _, ri := range mris {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return ri, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return MultiRewardIndex{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get fetches a RewardIndexes by it's denom
 | 
			
		||||
func (mris MultiRewardIndexes) Get(denom string) (RewardIndexes, bool) {
 | 
			
		||||
	for _, mri := range mris {
 | 
			
		||||
		if mri.CollateralType == denom {
 | 
			
		||||
			return mri.RewardIndexes, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRewardIndexIndex fetches a specific reward index inside the array by its denom
 | 
			
		||||
func (mris MultiRewardIndexes) GetRewardIndexIndex(denom string) (int, bool) {
 | 
			
		||||
	for i, ri := range mris {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			return i, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// With returns a copy of the indexes with a new RewardIndexes added
 | 
			
		||||
func (mris MultiRewardIndexes) With(denom string, indexes RewardIndexes) MultiRewardIndexes {
 | 
			
		||||
	newIndexes := mris.copy()
 | 
			
		||||
 | 
			
		||||
	for i, mri := range newIndexes {
 | 
			
		||||
		if mri.CollateralType == denom {
 | 
			
		||||
			newIndexes[i].RewardIndexes = indexes
 | 
			
		||||
			return newIndexes
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return append(newIndexes, NewMultiRewardIndex(denom, indexes))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetCollateralTypes returns a slice of containing all collateral types
 | 
			
		||||
func (mris MultiRewardIndexes) GetCollateralTypes() []string {
 | 
			
		||||
	var collateralTypes []string
 | 
			
		||||
	for _, ri := range mris {
 | 
			
		||||
		collateralTypes = append(collateralTypes, ri.CollateralType)
 | 
			
		||||
	}
 | 
			
		||||
	return collateralTypes
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveRewardIndex removes a denom's reward interest factor value
 | 
			
		||||
func (mris MultiRewardIndexes) RemoveRewardIndex(denom string) MultiRewardIndexes {
 | 
			
		||||
	for i, ri := range mris {
 | 
			
		||||
		if ri.CollateralType == denom {
 | 
			
		||||
			// copy the slice and underlying array to avoid altering the original
 | 
			
		||||
			copy := mris.copy()
 | 
			
		||||
			return append(copy[:i], copy[i+1:]...)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return mris
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate validation for reward indexes
 | 
			
		||||
func (mris MultiRewardIndexes) Validate() error {
 | 
			
		||||
	for _, mri := range mris {
 | 
			
		||||
		if err := mri.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// copy returns a copy of the slice and underlying array
 | 
			
		||||
func (mris MultiRewardIndexes) copy() MultiRewardIndexes {
 | 
			
		||||
	newIndexes := make(MultiRewardIndexes, len(mris))
 | 
			
		||||
	copy(newIndexes, mris)
 | 
			
		||||
	return newIndexes
 | 
			
		||||
}
 | 
			
		||||
@ -167,12 +167,12 @@ type HardLiquidityProviderClaim struct {
 | 
			
		||||
	BaseMultiClaim         `json:"base_claim" yaml:"base_claim"`
 | 
			
		||||
	SupplyRewardIndexes    MultiRewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"`
 | 
			
		||||
	BorrowRewardIndexes    MultiRewardIndexes `json:"borrow_reward_indexes" yaml:"borrow_reward_indexes"`
 | 
			
		||||
	DelegatorRewardIndexes RewardIndexes      `json:"delegator_reward_indexes" yaml:"delegator_reward_indexes"`
 | 
			
		||||
	DelegatorRewardIndexes MultiRewardIndexes `json:"delegator_reward_indexes" yaml:"delegator_reward_indexes"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewHardLiquidityProviderClaim returns a new HardLiquidityProviderClaim
 | 
			
		||||
func NewHardLiquidityProviderClaim(owner sdk.AccAddress, rewards sdk.Coins, supplyRewardIndexes,
 | 
			
		||||
	borrowRewardIndexes MultiRewardIndexes, delegatorRewardIndexes RewardIndexes) HardLiquidityProviderClaim {
 | 
			
		||||
	borrowRewardIndexes, delegatorRewardIndexes MultiRewardIndexes) HardLiquidityProviderClaim {
 | 
			
		||||
	return HardLiquidityProviderClaim{
 | 
			
		||||
		BaseMultiClaim: BaseMultiClaim{
 | 
			
		||||
			Owner:  owner,
 | 
			
		||||
 | 
			
		||||
@ -54,7 +54,7 @@ func TestGenesisStateValidate(t *testing.T) {
 | 
			
		||||
					},
 | 
			
		||||
					DefaultMultiRewardPeriods,
 | 
			
		||||
					DefaultMultiRewardPeriods,
 | 
			
		||||
					DefaultRewardPeriods,
 | 
			
		||||
					DefaultMultiRewardPeriods,
 | 
			
		||||
					Multipliers{
 | 
			
		||||
						NewMultiplier(Small, 1, sdk.MustNewDecFromStr("0.33")),
 | 
			
		||||
					},
 | 
			
		||||
 | 
			
		||||
@ -27,11 +27,11 @@ var (
 | 
			
		||||
	USDXMintingRewardFactorKeyPrefix                = []byte{0x02} // prefix for key that stores USDX minting reward factors
 | 
			
		||||
	PreviousUSDXMintingRewardAccrualTimeKeyPrefix   = []byte{0x03} // prefix for key that stores the blocktime
 | 
			
		||||
	HardLiquidityClaimKeyPrefix                     = []byte{0x04} // prefix for keys that store Hard liquidity claims
 | 
			
		||||
	HardSupplyRewardIndexesKeyPrefix                = []byte{0x05} // prefix for key that stores Hard supply reward factors
 | 
			
		||||
	HardSupplyRewardIndexesKeyPrefix                = []byte{0x05} // prefix for key that stores Hard supply reward indexes
 | 
			
		||||
	PreviousHardSupplyRewardAccrualTimeKeyPrefix    = []byte{0x06} // prefix for key that stores the previous time Hard supply rewards accrued
 | 
			
		||||
	HardBorrowRewardIndexesKeyPrefix                = []byte{0x07} // prefix for key that stores Hard borrow reward factors
 | 
			
		||||
	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
 | 
			
		||||
	HardDelegatorRewardFactorKeyPrefix              = []byte{0x09} // prefix for key that stores Hard delegator reward factors
 | 
			
		||||
	HardDelegatorRewardIndexesKeyPrefix             = []byte{0x09} // prefix for key that stores Hard delegator reward indexes
 | 
			
		||||
	PreviousHardDelegatorRewardAccrualTimeKeyPrefix = []byte{0x10} // prefix for key that stores the previous time Hard delegator rewards accrued
 | 
			
		||||
 | 
			
		||||
	USDXMintingRewardDenom   = "ukava"
 | 
			
		||||
 | 
			
		||||
@ -48,14 +48,14 @@ type Params struct {
 | 
			
		||||
	USDXMintingRewardPeriods   RewardPeriods      `json:"usdx_minting_reward_periods" yaml:"usdx_minting_reward_periods"`
 | 
			
		||||
	HardSupplyRewardPeriods    MultiRewardPeriods `json:"hard_supply_reward_periods" yaml:"hard_supply_reward_periods"`
 | 
			
		||||
	HardBorrowRewardPeriods    MultiRewardPeriods `json:"hard_borrow_reward_periods" yaml:"hard_borrow_reward_periods"`
 | 
			
		||||
	HardDelegatorRewardPeriods RewardPeriods      `json:"hard_delegator_reward_periods" yaml:"hard_delegator_reward_periods"`
 | 
			
		||||
	HardDelegatorRewardPeriods MultiRewardPeriods `json:"hard_delegator_reward_periods" yaml:"hard_delegator_reward_periods"`
 | 
			
		||||
	ClaimMultipliers           Multipliers        `json:"claim_multipliers" yaml:"claim_multipliers"`
 | 
			
		||||
	ClaimEnd                   time.Time          `json:"claim_end" yaml:"claim_end"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewParams returns a new params object
 | 
			
		||||
func NewParams(usdxMinting RewardPeriods, hardSupply, hardBorrow MultiRewardPeriods,
 | 
			
		||||
	hardDelegator RewardPeriods, multipliers Multipliers, claimEnd time.Time) Params {
 | 
			
		||||
func NewParams(usdxMinting RewardPeriods, hardSupply, hardBorrow, hardDelegator MultiRewardPeriods,
 | 
			
		||||
	multipliers Multipliers, claimEnd time.Time) Params {
 | 
			
		||||
	return Params{
 | 
			
		||||
		USDXMintingRewardPeriods:   usdxMinting,
 | 
			
		||||
		HardSupplyRewardPeriods:    hardSupply,
 | 
			
		||||
@ -69,7 +69,9 @@ func NewParams(usdxMinting RewardPeriods, hardSupply, hardBorrow MultiRewardPeri
 | 
			
		||||
// DefaultParams returns default params for incentive module
 | 
			
		||||
func DefaultParams() Params {
 | 
			
		||||
	return NewParams(DefaultRewardPeriods, DefaultMultiRewardPeriods,
 | 
			
		||||
		DefaultMultiRewardPeriods, DefaultRewardPeriods, DefaultMultipliers, DefaultClaimEnd)
 | 
			
		||||
		DefaultMultiRewardPeriods, DefaultMultiRewardPeriods,
 | 
			
		||||
		DefaultMultipliers, DefaultClaimEnd,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String implements fmt.Stringer
 | 
			
		||||
@ -96,7 +98,7 @@ func (p *Params) ParamSetPairs() params.ParamSetPairs {
 | 
			
		||||
		params.NewParamSetPair(KeyUSDXMintingRewardPeriods, &p.USDXMintingRewardPeriods, validateRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyHardSupplyRewardPeriods, &p.HardSupplyRewardPeriods, validateMultiRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyHardBorrowRewardPeriods, &p.HardBorrowRewardPeriods, validateMultiRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyHardDelegatorRewardPeriods, &p.HardDelegatorRewardPeriods, validateRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyHardDelegatorRewardPeriods, &p.HardDelegatorRewardPeriods, validateMultiRewardPeriodsParam),
 | 
			
		||||
		params.NewParamSetPair(KeyClaimEnd, &p.ClaimEnd, validateClaimEndParam),
 | 
			
		||||
		params.NewParamSetPair(KeyMultipliers, &p.ClaimMultipliers, validateMultipliersParam),
 | 
			
		||||
	}
 | 
			
		||||
@ -121,7 +123,7 @@ func (p Params) Validate() error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return validateRewardPeriodsParam(p.HardDelegatorRewardPeriods)
 | 
			
		||||
	return validateMultiRewardPeriodsParam(p.HardDelegatorRewardPeriods)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func validateRewardPeriodsParam(i interface{}) error {
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ func (suite *ParamTestSuite) TestParamValidation() {
 | 
			
		||||
		usdxMintingRewardPeriods   types.RewardPeriods
 | 
			
		||||
		hardSupplyRewardPeriods    types.MultiRewardPeriods
 | 
			
		||||
		hardBorrowRewardPeriods    types.MultiRewardPeriods
 | 
			
		||||
		hardDelegatorRewardPeriods types.RewardPeriods
 | 
			
		||||
		hardDelegatorRewardPeriods types.MultiRewardPeriods
 | 
			
		||||
		multipliers                types.Multipliers
 | 
			
		||||
		end                        time.Time
 | 
			
		||||
	}
 | 
			
		||||
@ -45,7 +45,7 @@ func (suite *ParamTestSuite) TestParamValidation() {
 | 
			
		||||
				usdxMintingRewardPeriods:   types.DefaultRewardPeriods,
 | 
			
		||||
				hardSupplyRewardPeriods:    types.DefaultMultiRewardPeriods,
 | 
			
		||||
				hardBorrowRewardPeriods:    types.DefaultMultiRewardPeriods,
 | 
			
		||||
				hardDelegatorRewardPeriods: types.DefaultRewardPeriods,
 | 
			
		||||
				hardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods,
 | 
			
		||||
				multipliers:                types.DefaultMultipliers,
 | 
			
		||||
				end:                        types.DefaultClaimEnd,
 | 
			
		||||
			},
 | 
			
		||||
@ -70,7 +70,7 @@ func (suite *ParamTestSuite) TestParamValidation() {
 | 
			
		||||
				},
 | 
			
		||||
				hardSupplyRewardPeriods:    types.DefaultMultiRewardPeriods,
 | 
			
		||||
				hardBorrowRewardPeriods:    types.DefaultMultiRewardPeriods,
 | 
			
		||||
				hardDelegatorRewardPeriods: types.DefaultRewardPeriods,
 | 
			
		||||
				hardDelegatorRewardPeriods: types.DefaultMultiRewardPeriods,
 | 
			
		||||
				end:                        time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC),
 | 
			
		||||
			},
 | 
			
		||||
			errArgs{
 | 
			
		||||
 | 
			
		||||
@ -117,22 +117,22 @@ func NewQueryRewardFactorsParams(denom string) QueryRewardFactorsParams {
 | 
			
		||||
 | 
			
		||||
// RewardFactor is a unique type returned by reward factor queries
 | 
			
		||||
type RewardFactor struct {
 | 
			
		||||
	Denom                     string        `json:"denom" yaml:"denom"`
 | 
			
		||||
	USDXMintingRewardFactor   sdk.Dec       `json:"usdx_minting_reward_factor" yaml:"usdx_minting_reward_factor"`
 | 
			
		||||
	HardSupplyRewardFactors   RewardIndexes `json:"hard_supply_reward_factors" yaml:"hard_supply_reward_factors"`
 | 
			
		||||
	HardBorrowRewardFactors   RewardIndexes `json:"hard_borrow_reward_factors" yaml:"hard_borrow_reward_factors"`
 | 
			
		||||
	HardDelegatorRewardFactor sdk.Dec       `json:"hard_delegator_reward_factor" yaml:"hard_delegator_reward_factor"`
 | 
			
		||||
	Denom                      string        `json:"denom" yaml:"denom"`
 | 
			
		||||
	USDXMintingRewardFactor    sdk.Dec       `json:"usdx_minting_reward_factor" yaml:"usdx_minting_reward_factor"`
 | 
			
		||||
	HardSupplyRewardFactors    RewardIndexes `json:"hard_supply_reward_factors" yaml:"hard_supply_reward_factors"`
 | 
			
		||||
	HardBorrowRewardFactors    RewardIndexes `json:"hard_borrow_reward_factors" yaml:"hard_borrow_reward_factors"`
 | 
			
		||||
	HardDelegatorRewardFactors RewardIndexes `json:"hard_delegator_reward_factors" yaml:"hard_delegator_reward_factors"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewRewardFactor returns a new instance of RewardFactor
 | 
			
		||||
func NewRewardFactor(denom string, usdxMintingRewardFactor sdk.Dec, hardSupplyRewardFactors,
 | 
			
		||||
	hardBorrowRewardFactors RewardIndexes, hardDelegatorRewardFactor sdk.Dec) RewardFactor {
 | 
			
		||||
	hardBorrowRewardFactors, hardDelegatorRewardFactors RewardIndexes) RewardFactor {
 | 
			
		||||
	return RewardFactor{
 | 
			
		||||
		Denom:                     denom,
 | 
			
		||||
		USDXMintingRewardFactor:   usdxMintingRewardFactor,
 | 
			
		||||
		HardSupplyRewardFactors:   hardSupplyRewardFactors,
 | 
			
		||||
		HardBorrowRewardFactors:   hardBorrowRewardFactors,
 | 
			
		||||
		HardDelegatorRewardFactor: hardDelegatorRewardFactor,
 | 
			
		||||
		Denom:                      denom,
 | 
			
		||||
		USDXMintingRewardFactor:    usdxMintingRewardFactor,
 | 
			
		||||
		HardSupplyRewardFactors:    hardSupplyRewardFactors,
 | 
			
		||||
		HardBorrowRewardFactors:    hardBorrowRewardFactors,
 | 
			
		||||
		HardDelegatorRewardFactors: hardDelegatorRewardFactors,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user