mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-04-04 15:55:23 +00:00 
			
		
		
		
	[R4R] re-enable claiming rewards validator vesting accounts (#920)
* feat: add new msg types for claim rewards from validator vesting accounts * fix: validate owner is validator vesting account * feat: add validator vesting tests for incent claims * address review comments * fix: client command name and example
This commit is contained in:
		
							parent
							
								
									fc85052522
								
							
						
					
					
						commit
						4d6f6aab3c
					
				| @ -1,154 +1,175 @@ | ||||
| // nolint
 | ||||
| // autogenerated code using github.com/rigelrozanski/multitool
 | ||||
| // aliases generated for the following subdirectories:
 | ||||
| // ALIASGEN: github.com/kava-labs/kava/x/incentive/types
 | ||||
| // ALIASGEN: github.com/kava-labs/kava/x/incentive/keeper
 | ||||
| package incentive | ||||
| 
 | ||||
| // DO NOT EDIT - generated by aliasgen tool (github.com/rhuairahrighairidh/aliasgen)
 | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/kava-labs/kava/x/incentive/keeper" | ||||
| 	"github.com/kava-labs/kava/x/incentive/types" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	BeginningOfMonth               = keeper.BeginningOfMonth | ||||
| 	MidMonth                       = keeper.MidMonth | ||||
| 	PaymentHour                    = keeper.PaymentHour | ||||
| 	AttributeKeyClaimAmount        = types.AttributeKeyClaimAmount | ||||
| 	AttributeKeyClaimPeriod        = types.AttributeKeyClaimPeriod | ||||
| 	AttributeKeyClaimType          = types.AttributeKeyClaimType | ||||
| 	AttributeKeyClaimedBy          = types.AttributeKeyClaimedBy | ||||
| 	AttributeKeyRewardPeriod       = types.AttributeKeyRewardPeriod | ||||
| 	AttributeValueCategory         = types.AttributeValueCategory | ||||
| 	BondDenom                      = types.BondDenom | ||||
| 	DefaultParamspace              = types.DefaultParamspace | ||||
| 	EventTypeClaim                 = types.EventTypeClaim | ||||
| 	EventTypeClaimPeriod           = types.EventTypeClaimPeriod | ||||
| 	EventTypeClaimPeriodExpiry     = types.EventTypeClaimPeriodExpiry | ||||
| 	EventTypeRewardPeriod          = types.EventTypeRewardPeriod | ||||
| 	HardLiquidityProviderClaimType = types.HardLiquidityProviderClaimType | ||||
| 	Large                          = types.Large | ||||
| 	Medium                         = types.Medium | ||||
| 	ModuleName                     = types.ModuleName | ||||
| 	QuerierRoute                   = types.QuerierRoute | ||||
| 	QueryGetClaimPeriods           = types.QueryGetClaimPeriods | ||||
| 	QueryGetHardRewards            = types.QueryGetHardRewards | ||||
| 	QueryGetParams                 = types.QueryGetParams | ||||
| 	QueryGetRewardPeriods          = types.QueryGetRewardPeriods | ||||
| 	QueryGetRewards                = types.QueryGetRewards | ||||
| 	QueryGetUSDXMintingRewards     = types.QueryGetUSDXMintingRewards | ||||
| 	RestClaimCollateralType        = types.RestClaimCollateralType | ||||
| 	RestClaimOwner                 = types.RestClaimOwner | ||||
| 	RestClaimType                  = types.RestClaimType | ||||
| 	RouterKey                      = types.RouterKey | ||||
| 	Small                          = types.Small | ||||
| 	StoreKey                       = types.StoreKey | ||||
| 	USDXMintingClaimType           = types.USDXMintingClaimType | ||||
| 	USDXMintingClaimType               = types.USDXMintingClaimType | ||||
| 	HardLiquidityProviderClaimType     = types.HardLiquidityProviderClaimType | ||||
| 	BondDenom                          = types.BondDenom | ||||
| 	EventTypeClaim                     = types.EventTypeClaim | ||||
| 	EventTypeRewardPeriod              = types.EventTypeRewardPeriod | ||||
| 	EventTypeClaimPeriod               = types.EventTypeClaimPeriod | ||||
| 	EventTypeClaimPeriodExpiry         = types.EventTypeClaimPeriodExpiry | ||||
| 	AttributeValueCategory             = types.AttributeValueCategory | ||||
| 	AttributeKeyClaimedBy              = types.AttributeKeyClaimedBy | ||||
| 	AttributeKeyClaimAmount            = types.AttributeKeyClaimAmount | ||||
| 	AttributeKeyClaimType              = types.AttributeKeyClaimType | ||||
| 	AttributeKeyRewardPeriod           = types.AttributeKeyRewardPeriod | ||||
| 	AttributeKeyClaimPeriod            = types.AttributeKeyClaimPeriod | ||||
| 	ModuleName                         = types.ModuleName | ||||
| 	StoreKey                           = types.StoreKey | ||||
| 	RouterKey                          = types.RouterKey | ||||
| 	DefaultParamspace                  = types.DefaultParamspace | ||||
| 	QuerierRoute                       = types.QuerierRoute | ||||
| 	Small                              = types.Small | ||||
| 	Medium                             = types.Medium | ||||
| 	Large                              = types.Large | ||||
| 	QueryGetRewards                    = types.QueryGetRewards | ||||
| 	QueryGetHardRewards                = types.QueryGetHardRewards | ||||
| 	QueryGetHardRewardsUnsynced        = types.QueryGetHardRewardsUnsynced | ||||
| 	QueryGetUSDXMintingRewards         = types.QueryGetUSDXMintingRewards | ||||
| 	QueryGetUSDXMintingRewardsUnsynced = types.QueryGetUSDXMintingRewardsUnsynced | ||||
| 	QueryGetRewardFactors              = types.QueryGetRewardFactors | ||||
| 	QueryGetParams                     = types.QueryGetParams | ||||
| 	QueryGetRewardPeriods              = types.QueryGetRewardPeriods | ||||
| 	QueryGetClaimPeriods               = types.QueryGetClaimPeriods | ||||
| 	RestClaimCollateralType            = types.RestClaimCollateralType | ||||
| 	RestClaimOwner                     = types.RestClaimOwner | ||||
| 	RestClaimType                      = types.RestClaimType | ||||
| 	RestUnsynced                       = types.RestUnsynced | ||||
| 	BeginningOfMonth                   = keeper.BeginningOfMonth | ||||
| 	MidMonth                           = keeper.MidMonth | ||||
| 	PaymentHour                        = keeper.PaymentHour | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	// function aliases
 | ||||
| 	CalculateTimeElapsed             = keeper.CalculateTimeElapsed | ||||
| 	NewKeeper                        = keeper.NewKeeper | ||||
| 	NewQuerier                       = keeper.NewQuerier | ||||
| 	DefaultGenesisState              = types.DefaultGenesisState | ||||
| 	DefaultParams                    = types.DefaultParams | ||||
| 	GetTotalVestingPeriodLength      = types.GetTotalVestingPeriodLength | ||||
| 	NewGenesisAccumulationTime       = types.NewGenesisAccumulationTime | ||||
| 	NewGenesisState                  = types.NewGenesisState | ||||
| 	NewHardLiquidityProviderClaim    = types.NewHardLiquidityProviderClaim | ||||
| 	NewMsgClaimHardReward            = types.NewMsgClaimHardReward | ||||
| 	NewMsgClaimUSDXMintingReward     = types.NewMsgClaimUSDXMintingReward | ||||
| 	NewMultiRewardIndex              = types.NewMultiRewardIndex | ||||
| 	NewMultiRewardPeriod             = types.NewMultiRewardPeriod | ||||
| 	NewMultiplier                    = types.NewMultiplier | ||||
| 	NewParams                        = types.NewParams | ||||
| 	NewPeriod                        = types.NewPeriod | ||||
| 	NewQueryHardRewardsParams        = types.NewQueryHardRewardsParams | ||||
| 	NewQueryRewardsParams            = types.NewQueryRewardsParams | ||||
| 	NewQueryUSDXMintingRewardsParams = types.NewQueryUSDXMintingRewardsParams | ||||
| 	NewRewardIndex                   = types.NewRewardIndex | ||||
| 	NewRewardPeriod                  = types.NewRewardPeriod | ||||
| 	NewUSDXMintingClaim              = types.NewUSDXMintingClaim | ||||
| 	ParamKeyTable                    = types.ParamKeyTable | ||||
| 	RegisterCodec                    = types.RegisterCodec | ||||
| 	// functions aliases
 | ||||
| 	GetTotalVestingPeriodLength              = types.GetTotalVestingPeriodLength | ||||
| 	NewUSDXMintingClaim                      = types.NewUSDXMintingClaim | ||||
| 	NewHardLiquidityProviderClaim            = types.NewHardLiquidityProviderClaim | ||||
| 	NewMultiRewardPeriod                     = types.NewMultiRewardPeriod | ||||
| 	NewRewardIndex                           = types.NewRewardIndex | ||||
| 	NewMultiRewardIndex                      = types.NewMultiRewardIndex | ||||
| 	RegisterCodec                            = types.RegisterCodec | ||||
| 	NewGenesisState                          = types.NewGenesisState | ||||
| 	DefaultGenesisState                      = types.DefaultGenesisState | ||||
| 	NewGenesisAccumulationTime               = types.NewGenesisAccumulationTime | ||||
| 	NewMsgClaimUSDXMintingReward             = types.NewMsgClaimUSDXMintingReward | ||||
| 	NewMsgClaimUSDXMintingRewardVVesting     = types.NewMsgClaimUSDXMintingRewardVVesting | ||||
| 	NewMsgClaimHardReward                    = types.NewMsgClaimHardReward | ||||
| 	NewMsgClaimHardRewardVVesting            = types.NewMsgClaimHardRewardVVesting | ||||
| 	NewParams                                = types.NewParams | ||||
| 	DefaultParams                            = types.DefaultParams | ||||
| 	ParamKeyTable                            = types.ParamKeyTable | ||||
| 	NewRewardPeriod                          = types.NewRewardPeriod | ||||
| 	NewMultiplier                            = types.NewMultiplier | ||||
| 	NewPeriod                                = types.NewPeriod | ||||
| 	NewQueryRewardsParams                    = types.NewQueryRewardsParams | ||||
| 	NewQueryUSDXMintingRewardsParams         = types.NewQueryUSDXMintingRewardsParams | ||||
| 	NewQueryUSDXMintingRewardsUnsyncedParams = types.NewQueryUSDXMintingRewardsUnsyncedParams | ||||
| 	NewQueryHardRewardsParams                = types.NewQueryHardRewardsParams | ||||
| 	NewQueryHardRewardsUnsyncedParams        = types.NewQueryHardRewardsUnsyncedParams | ||||
| 	NewQueryRewardFactorsParams              = types.NewQueryRewardFactorsParams | ||||
| 	NewRewardFactor                          = types.NewRewardFactor | ||||
| 	NewKeeper                                = keeper.NewKeeper | ||||
| 	NewQuerier                               = keeper.NewQuerier | ||||
| 	CalculateTimeElapsed                     = keeper.CalculateTimeElapsed | ||||
| 
 | ||||
| 	// variable aliases
 | ||||
| 	DefaultActive                                   = types.DefaultActive | ||||
| 	DefaultClaimEnd                                 = types.DefaultClaimEnd | ||||
| 	DefaultGenesisAccumulationTimes                 = types.DefaultGenesisAccumulationTimes | ||||
| 	DefaultHardClaims                               = types.DefaultHardClaims | ||||
| 	DefaultMultiRewardPeriods                       = types.DefaultMultiRewardPeriods | ||||
| 	DefaultMultipliers                              = types.DefaultMultipliers | ||||
| 	DefaultRewardPeriods                            = types.DefaultRewardPeriods | ||||
| 	DefaultUSDXClaims                               = types.DefaultUSDXClaims | ||||
| 	ErrAccountNotFound                              = types.ErrAccountNotFound | ||||
| 	ErrClaimExpired                                 = types.ErrClaimExpired | ||||
| 	ModuleCdc                                       = types.ModuleCdc | ||||
| 	ErrClaimNotFound                                = types.ErrClaimNotFound | ||||
| 	ErrInsufficientModAccountBalance                = types.ErrInsufficientModAccountBalance | ||||
| 	ErrInvalidAccountType                           = types.ErrInvalidAccountType | ||||
| 	ErrInvalidClaimType                             = types.ErrInvalidClaimType | ||||
| 	ErrInvalidMultiplier                            = types.ErrInvalidMultiplier | ||||
| 	ErrNoClaimsFound                                = types.ErrNoClaimsFound | ||||
| 	ErrRewardPeriodNotFound                         = types.ErrRewardPeriodNotFound | ||||
| 	ErrInvalidAccountType                           = types.ErrInvalidAccountType | ||||
| 	ErrNoClaimsFound                                = types.ErrNoClaimsFound | ||||
| 	ErrInsufficientModAccountBalance                = types.ErrInsufficientModAccountBalance | ||||
| 	ErrAccountNotFound                              = types.ErrAccountNotFound | ||||
| 	ErrInvalidMultiplier                            = types.ErrInvalidMultiplier | ||||
| 	ErrZeroClaim                                    = types.ErrZeroClaim | ||||
| 	GovDenom                                        = types.GovDenom | ||||
| 	HardBorrowRewardIndexesKeyPrefix                = types.HardBorrowRewardIndexesKeyPrefix | ||||
| 	HardDelegatorRewardFactorKeyPrefix              = types.HardDelegatorRewardFactorKeyPrefix | ||||
| 	ErrClaimExpired                                 = types.ErrClaimExpired | ||||
| 	ErrInvalidClaimType                             = types.ErrInvalidClaimType | ||||
| 	ErrInvalidClaimOwner                            = types.ErrInvalidClaimOwner | ||||
| 	USDXMintingClaimKeyPrefix                       = types.USDXMintingClaimKeyPrefix | ||||
| 	USDXMintingRewardFactorKeyPrefix                = types.USDXMintingRewardFactorKeyPrefix | ||||
| 	PreviousUSDXMintingRewardAccrualTimeKeyPrefix   = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix | ||||
| 	HardLiquidityClaimKeyPrefix                     = types.HardLiquidityClaimKeyPrefix | ||||
| 	HardLiquidityRewardDenom                        = types.HardLiquidityRewardDenom | ||||
| 	HardSupplyRewardIndexesKeyPrefix                = types.HardSupplyRewardIndexesKeyPrefix | ||||
| 	IncentiveMacc                                   = types.IncentiveMacc | ||||
| 	KeyClaimEnd                                     = types.KeyClaimEnd | ||||
| 	PreviousHardSupplyRewardAccrualTimeKeyPrefix    = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix | ||||
| 	HardBorrowRewardIndexesKeyPrefix                = types.HardBorrowRewardIndexesKeyPrefix | ||||
| 	PreviousHardBorrowRewardAccrualTimeKeyPrefix    = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix | ||||
| 	HardDelegatorRewardFactorKeyPrefix              = types.HardDelegatorRewardFactorKeyPrefix | ||||
| 	PreviousHardDelegatorRewardAccrualTimeKeyPrefix = types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix | ||||
| 	USDXMintingRewardDenom                          = types.USDXMintingRewardDenom | ||||
| 	HardLiquidityRewardDenom                        = types.HardLiquidityRewardDenom | ||||
| 	KeyUSDXMintingRewardPeriods                     = types.KeyUSDXMintingRewardPeriods | ||||
| 	KeyHardSupplyRewardPeriods                      = types.KeyHardSupplyRewardPeriods | ||||
| 	KeyHardBorrowRewardPeriods                      = types.KeyHardBorrowRewardPeriods | ||||
| 	KeyHardDelegatorRewardPeriods                   = types.KeyHardDelegatorRewardPeriods | ||||
| 	KeyHardSupplyRewardPeriods                      = types.KeyHardSupplyRewardPeriods | ||||
| 	KeyClaimEnd                                     = types.KeyClaimEnd | ||||
| 	KeyMultipliers                                  = types.KeyMultipliers | ||||
| 	KeyUSDXMintingRewardPeriods                     = types.KeyUSDXMintingRewardPeriods | ||||
| 	ModuleCdc                                       = types.ModuleCdc | ||||
| 	PreviousHardBorrowRewardAccrualTimeKeyPrefix    = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix | ||||
| 	PreviousHardDelegatorRewardAccrualTimeKeyPrefix = types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix | ||||
| 	PreviousHardSupplyRewardAccrualTimeKeyPrefix    = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix | ||||
| 	PreviousUSDXMintingRewardAccrualTimeKeyPrefix   = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix | ||||
| 	DefaultActive                                   = types.DefaultActive | ||||
| 	DefaultRewardPeriods                            = types.DefaultRewardPeriods | ||||
| 	DefaultMultiRewardPeriods                       = types.DefaultMultiRewardPeriods | ||||
| 	DefaultMultipliers                              = types.DefaultMultipliers | ||||
| 	DefaultUSDXClaims                               = types.DefaultUSDXClaims | ||||
| 	DefaultHardClaims                               = types.DefaultHardClaims | ||||
| 	DefaultGenesisAccumulationTimes                 = types.DefaultGenesisAccumulationTimes | ||||
| 	DefaultClaimEnd                                 = types.DefaultClaimEnd | ||||
| 	GovDenom                                        = types.GovDenom | ||||
| 	PrincipalDenom                                  = types.PrincipalDenom | ||||
| 	USDXMintingClaimKeyPrefix                       = types.USDXMintingClaimKeyPrefix | ||||
| 	USDXMintingRewardDenom                          = types.USDXMintingRewardDenom | ||||
| 	USDXMintingRewardFactorKeyPrefix                = types.USDXMintingRewardFactorKeyPrefix | ||||
| 	IncentiveMacc                                   = types.IncentiveMacc | ||||
| ) | ||||
| 
 | ||||
| type ( | ||||
| 	Hooks                         = keeper.Hooks | ||||
| 	Keeper                        = keeper.Keeper | ||||
| 	AccountKeeper                 = types.AccountKeeper | ||||
| 	BaseClaim                     = types.BaseClaim | ||||
| 	BaseMultiClaim                = types.BaseMultiClaim | ||||
| 	CDPHooks                      = types.CDPHooks | ||||
| 	CdpKeeper                     = types.CdpKeeper | ||||
| 	Claim                         = types.Claim | ||||
| 	Claims                        = types.Claims | ||||
| 	GenesisAccumulationTime       = types.GenesisAccumulationTime | ||||
| 	GenesisAccumulationTimes      = types.GenesisAccumulationTimes | ||||
| 	GenesisState                  = types.GenesisState | ||||
| 	HARDHooks                     = types.HARDHooks | ||||
| 	HardKeeper                    = types.HardKeeper | ||||
| 	HardLiquidityProviderClaim    = types.HardLiquidityProviderClaim | ||||
| 	HardLiquidityProviderClaims   = types.HardLiquidityProviderClaims | ||||
| 	MsgClaimHardReward            = types.MsgClaimHardReward | ||||
| 	MsgClaimUSDXMintingReward     = types.MsgClaimUSDXMintingReward | ||||
| 	MultiRewardIndex              = types.MultiRewardIndex | ||||
| 	MultiRewardIndexes            = types.MultiRewardIndexes | ||||
| 	MultiRewardPeriod             = types.MultiRewardPeriod | ||||
| 	MultiRewardPeriods            = types.MultiRewardPeriods | ||||
| 	Multiplier                    = types.Multiplier | ||||
| 	MultiplierName                = types.MultiplierName | ||||
| 	Multipliers                   = types.Multipliers | ||||
| 	Params                        = types.Params | ||||
| 	QueryHardRewardsParams        = types.QueryHardRewardsParams | ||||
| 	QueryRewardsParams            = types.QueryRewardsParams | ||||
| 	QueryUSDXMintingRewardsParams = types.QueryUSDXMintingRewardsParams | ||||
| 	RewardIndex                   = types.RewardIndex | ||||
| 	RewardIndexes                 = types.RewardIndexes | ||||
| 	RewardPeriod                  = types.RewardPeriod | ||||
| 	RewardPeriods                 = types.RewardPeriods | ||||
| 	StakingKeeper                 = types.StakingKeeper | ||||
| 	SupplyKeeper                  = types.SupplyKeeper | ||||
| 	USDXMintingClaim              = types.USDXMintingClaim | ||||
| 	USDXMintingClaims             = types.USDXMintingClaims | ||||
| 	Claim                                 = types.Claim | ||||
| 	Claims                                = types.Claims | ||||
| 	BaseClaim                             = types.BaseClaim | ||||
| 	BaseMultiClaim                        = types.BaseMultiClaim | ||||
| 	USDXMintingClaim                      = types.USDXMintingClaim | ||||
| 	USDXMintingClaims                     = types.USDXMintingClaims | ||||
| 	HardLiquidityProviderClaim            = types.HardLiquidityProviderClaim | ||||
| 	HardLiquidityProviderClaims           = types.HardLiquidityProviderClaims | ||||
| 	MultiRewardPeriod                     = types.MultiRewardPeriod | ||||
| 	MultiRewardPeriods                    = types.MultiRewardPeriods | ||||
| 	RewardIndex                           = types.RewardIndex | ||||
| 	RewardIndexes                         = types.RewardIndexes | ||||
| 	MultiRewardIndex                      = types.MultiRewardIndex | ||||
| 	MultiRewardIndexes                    = types.MultiRewardIndexes | ||||
| 	SupplyKeeper                          = types.SupplyKeeper | ||||
| 	StakingKeeper                         = types.StakingKeeper | ||||
| 	CdpKeeper                             = types.CdpKeeper | ||||
| 	HardKeeper                            = types.HardKeeper | ||||
| 	AccountKeeper                         = types.AccountKeeper | ||||
| 	CDPHooks                              = types.CDPHooks | ||||
| 	HARDHooks                             = types.HARDHooks | ||||
| 	GenesisState                          = types.GenesisState | ||||
| 	GenesisAccumulationTime               = types.GenesisAccumulationTime | ||||
| 	GenesisAccumulationTimes              = types.GenesisAccumulationTimes | ||||
| 	MsgClaimUSDXMintingReward             = types.MsgClaimUSDXMintingReward | ||||
| 	MsgClaimUSDXMintingRewardVVesting     = types.MsgClaimUSDXMintingRewardVVesting | ||||
| 	MsgClaimHardReward                    = types.MsgClaimHardReward | ||||
| 	MsgClaimHardRewardVVesting            = types.MsgClaimHardRewardVVesting | ||||
| 	Params                                = types.Params | ||||
| 	RewardPeriod                          = types.RewardPeriod | ||||
| 	RewardPeriods                         = types.RewardPeriods | ||||
| 	Multiplier                            = types.Multiplier | ||||
| 	Multipliers                           = types.Multipliers | ||||
| 	MultiplierName                        = types.MultiplierName | ||||
| 	QueryRewardsParams                    = types.QueryRewardsParams | ||||
| 	QueryUSDXMintingRewardsParams         = types.QueryUSDXMintingRewardsParams | ||||
| 	QueryUSDXMintingRewardsUnsyncedParams = types.QueryUSDXMintingRewardsUnsyncedParams | ||||
| 	QueryHardRewardsParams                = types.QueryHardRewardsParams | ||||
| 	QueryHardRewardsUnsyncedParams        = types.QueryHardRewardsUnsyncedParams | ||||
| 	QueryRewardFactorsParams              = types.QueryRewardFactorsParams | ||||
| 	RewardFactor                          = types.RewardFactor | ||||
| 	RewardFactors                         = types.RewardFactors | ||||
| 	Hooks                                 = keeper.Hooks | ||||
| 	Keeper                                = keeper.Keeper | ||||
| ) | ||||
|  | ||||
| @ -27,7 +27,9 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { | ||||
| 
 | ||||
| 	incentiveTxCmd.AddCommand(flags.PostCommands( | ||||
| 		getCmdClaimCdp(cdc), | ||||
| 		getCmdClaimCdpVVesting(cdc), | ||||
| 		getCmdClaimHard(cdc), | ||||
| 		getCmdClaimHardVVesting(cdc), | ||||
| 	)...) | ||||
| 
 | ||||
| 	return incentiveTxCmd | ||||
| @ -63,6 +65,76 @@ func getCmdClaimCdp(cdc *codec.Codec) *cobra.Command { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func getCmdClaimCdpVVesting(cdc *codec.Codec) *cobra.Command { | ||||
| 	return &cobra.Command{ | ||||
| 		Use:   "claim-cdp-vesting [multiplier] [receiver]", | ||||
| 		Short: "claim CDP rewards using a given multiplier on behalf of a validator vesting account", | ||||
| 		Long: strings.TrimSpace( | ||||
| 			fmt.Sprintf(`Claim sender's outstanding CDP rewards on behalf of a validator vesting using a given multiplier | ||||
| 
 | ||||
| 			Example: | ||||
| 			$ %s tx %s claim-cdp-vesting large kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw | ||||
| 		`, version.ClientName, types.ModuleName), | ||||
| 		), | ||||
| 		Args: cobra.ExactArgs(2), | ||||
| 		RunE: func(cmd *cobra.Command, args []string) error { | ||||
| 			inBuf := bufio.NewReader(cmd.InOrStdin()) | ||||
| 			cliCtx := context.NewCLIContext().WithCodec(cdc) | ||||
| 			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) | ||||
| 
 | ||||
| 			sender := cliCtx.GetFromAddress() | ||||
| 			multiplier := args[0] | ||||
| 			receiverStr := args[1] | ||||
| 			receiver, err := sdk.AccAddressFromBech32(receiverStr) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 
 | ||||
| 			msg := types.NewMsgClaimUSDXMintingRewardVVesting(sender, receiver, multiplier) | ||||
| 			err = msg.ValidateBasic() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func getCmdClaimHardVVesting(cdc *codec.Codec) *cobra.Command { | ||||
| 	return &cobra.Command{ | ||||
| 		Use:   "claim-hard-vesting [multiplier] [receiver]", | ||||
| 		Short: "claim Hard module rewards on behalf of a validator vesting account using a given multiplier", | ||||
| 		Long: strings.TrimSpace( | ||||
| 			fmt.Sprintf(`Claim sender's outstanding Hard rewards on behalf of a validator vesting account for deposit/borrow/delegate using given multiplier | ||||
| 
 | ||||
| 			Example: | ||||
| 			$ %s tx %s claim-hard-vesting large kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw | ||||
| 		`, version.ClientName, types.ModuleName), | ||||
| 		), | ||||
| 		Args: cobra.ExactArgs(2), | ||||
| 		RunE: func(cmd *cobra.Command, args []string) error { | ||||
| 			inBuf := bufio.NewReader(cmd.InOrStdin()) | ||||
| 			cliCtx := context.NewCLIContext().WithCodec(cdc) | ||||
| 			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc)) | ||||
| 
 | ||||
| 			sender := cliCtx.GetFromAddress() | ||||
| 			multiplier := args[0] | ||||
| 			receiverStr := args[1] | ||||
| 			receiver, err := sdk.AccAddressFromBech32(receiverStr) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 
 | ||||
| 			msg := types.NewMsgClaimHardRewardVVesting(sender, receiver, multiplier) | ||||
| 			err = msg.ValidateBasic() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}) | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func getCmdClaimHard(cdc *codec.Codec) *cobra.Command { | ||||
| 	return &cobra.Command{ | ||||
| 		Use:   "claim-hard [multiplier]", | ||||
|  | ||||
| @ -26,3 +26,11 @@ type PostClaimReq struct { | ||||
| 	Sender         sdk.AccAddress `json:"sender" yaml:"sender"` | ||||
| 	MultiplierName string         `json:"multiplier_name" yaml:"multiplier_name"` | ||||
| } | ||||
| 
 | ||||
| // PostClaimReq defines the properties of claim transaction's request body.
 | ||||
| type PostClaimVVestingReq struct { | ||||
| 	BaseReq        rest.BaseReq   `json:"base_req" yaml:"base_req"` | ||||
| 	Sender         sdk.AccAddress `json:"sender" yaml:"sender"` | ||||
| 	Receiver       sdk.AccAddress `json:"receiver" yaml:"receiver"` | ||||
| 	MultiplierName string         `json:"multiplier_name" yaml:"multiplier_name"` | ||||
| } | ||||
|  | ||||
| @ -17,7 +17,10 @@ import ( | ||||
| 
 | ||||
| func registerTxRoutes(cliCtx context.CLIContext, r *mux.Router) { | ||||
| 	r.HandleFunc("/incentive/claim-cdp", postClaimCdpHandlerFn(cliCtx)).Methods("POST") | ||||
| 	r.HandleFunc("/incentive/claim-cdp-vesting", postClaimCdpVVestingHandlerFn(cliCtx)).Methods("POST") | ||||
| 	r.HandleFunc("/incentive/claim-hard", postClaimHardHandlerFn(cliCtx)).Methods("POST") | ||||
| 	r.HandleFunc("/incentive/claim-hard-vesting", postClaimHardVVestingHandlerFn(cliCtx)).Methods("POST") | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func postClaimCdpHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||||
| @ -53,6 +56,39 @@ func postClaimCdpHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func postClaimCdpVVestingHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||||
| 	return func(w http.ResponseWriter, r *http.Request) { | ||||
| 		var requestBody PostClaimVVestingReq | ||||
| 		if !rest.ReadRESTReq(w, r, cliCtx.Codec, &requestBody) { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		requestBody.BaseReq = requestBody.BaseReq.Sanitize() | ||||
| 		if !requestBody.BaseReq.ValidateBasic(w) { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		fromAddr, err := sdk.AccAddressFromBech32(requestBody.BaseReq.From) | ||||
| 		if err != nil { | ||||
| 			rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if !bytes.Equal(fromAddr, requestBody.Sender) { | ||||
| 			rest.WriteErrorResponse(w, http.StatusUnauthorized, fmt.Sprintf("expected: %s, got: %s", fromAddr, requestBody.Sender)) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		msg := types.NewMsgClaimUSDXMintingRewardVVesting(requestBody.Sender, requestBody.Receiver, requestBody.MultiplierName) | ||||
| 		if err := msg.ValidateBasic(); err != nil { | ||||
| 			rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		utils.WriteGenerateStdTxResponse(w, cliCtx, requestBody.BaseReq, []sdk.Msg{msg}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func postClaimHardHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||||
| 	return func(w http.ResponseWriter, r *http.Request) { | ||||
| 		var requestBody PostClaimReq | ||||
| @ -85,3 +121,36 @@ func postClaimHardHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||||
| 		utils.WriteGenerateStdTxResponse(w, cliCtx, requestBody.BaseReq, []sdk.Msg{msg}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func postClaimHardVVestingHandlerFn(cliCtx context.CLIContext) http.HandlerFunc { | ||||
| 	return func(w http.ResponseWriter, r *http.Request) { | ||||
| 		var requestBody PostClaimVVestingReq | ||||
| 		if !rest.ReadRESTReq(w, r, cliCtx.Codec, &requestBody) { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		requestBody.BaseReq = requestBody.BaseReq.Sanitize() | ||||
| 		if !requestBody.BaseReq.ValidateBasic(w) { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		fromAddr, err := sdk.AccAddressFromBech32(requestBody.BaseReq.From) | ||||
| 		if err != nil { | ||||
| 			rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if !bytes.Equal(fromAddr, requestBody.Sender) { | ||||
| 			rest.WriteErrorResponse(w, http.StatusUnauthorized, fmt.Sprintf("expected: %s, got: %s", fromAddr, requestBody.Sender)) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		msg := types.NewMsgClaimHardRewardVVesting(requestBody.Sender, requestBody.Receiver, requestBody.MultiplierName) | ||||
| 		if err := msg.ValidateBasic(); err != nil { | ||||
| 			rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		utils.WriteGenerateStdTxResponse(w, cliCtx, requestBody.BaseReq, []sdk.Msg{msg}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -15,8 +15,12 @@ func NewHandler(k keeper.Keeper) sdk.Handler { | ||||
| 		switch msg := msg.(type) { | ||||
| 		case types.MsgClaimUSDXMintingReward: | ||||
| 			return handleMsgClaimUSDXMintingReward(ctx, k, msg) | ||||
| 		case types.MsgClaimUSDXMintingRewardVVesting: | ||||
| 			return handleMsgClaimUSDXMintingRewardVVesting(ctx, k, msg) | ||||
| 		case types.MsgClaimHardReward: | ||||
| 			return handleMsgClaimHardReward(ctx, k, msg) | ||||
| 		case types.MsgClaimHardRewardVVesting: | ||||
| 			return handleMsgClaimHardRewardVVesting(ctx, k, msg) | ||||
| 		default: | ||||
| 			return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg) | ||||
| 		} | ||||
| @ -24,7 +28,6 @@ func NewHandler(k keeper.Keeper) sdk.Handler { | ||||
| } | ||||
| 
 | ||||
| func handleMsgClaimUSDXMintingReward(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimUSDXMintingReward) (*sdk.Result, error) { | ||||
| 
 | ||||
| 	err := k.ClaimUSDXMintingReward(ctx, msg.Sender, types.MultiplierName(msg.MultiplierName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @ -34,6 +37,17 @@ func handleMsgClaimUSDXMintingReward(ctx sdk.Context, k keeper.Keeper, msg types | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func handleMsgClaimUSDXMintingRewardVVesting(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimUSDXMintingRewardVVesting) (*sdk.Result, error) { | ||||
| 
 | ||||
| 	err := k.ClaimUSDXMintingRewardVVesting(ctx, msg.Sender, msg.Receiver, types.MultiplierName(msg.MultiplierName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &sdk.Result{ | ||||
| 		Events: ctx.EventManager().Events(), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func handleMsgClaimHardReward(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimHardReward) (*sdk.Result, error) { | ||||
| 
 | ||||
| 	err := k.ClaimHardReward(ctx, msg.Sender, types.MultiplierName(msg.MultiplierName)) | ||||
| @ -44,3 +58,14 @@ func handleMsgClaimHardReward(ctx sdk.Context, k keeper.Keeper, msg types.MsgCla | ||||
| 		Events: ctx.EventManager().Events(), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func handleMsgClaimHardRewardVVesting(ctx sdk.Context, k keeper.Keeper, msg types.MsgClaimHardRewardVVesting) (*sdk.Result, error) { | ||||
| 
 | ||||
| 	err := k.ClaimHardRewardVVesting(ctx, msg.Sender, msg.Receiver, types.MultiplierName(msg.MultiplierName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &sdk.Result{ | ||||
| 		Events: ctx.EventManager().Events(), | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| @ -74,6 +74,66 @@ func (k Keeper) ClaimUSDXMintingReward(ctx sdk.Context, addr sdk.AccAddress, mul | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // ClaimUSDXMintingReward sends the reward amount to the input receiver address and zero's out the claim in the store
 | ||||
| func (k Keeper) ClaimUSDXMintingRewardVVesting(ctx sdk.Context, owner, receiver sdk.AccAddress, multiplierName types.MultiplierName) error { | ||||
| 	claim, found := k.GetUSDXMintingClaim(ctx, owner) | ||||
| 	if !found { | ||||
| 		return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", owner) | ||||
| 	} | ||||
| 
 | ||||
| 	acc := k.accountKeeper.GetAccount(ctx, owner) | ||||
| 	if acc == nil { | ||||
| 		return sdkerrors.Wrapf(types.ErrAccountNotFound, "address not found: %s", owner) | ||||
| 	} | ||||
| 	_, ok := acc.(*validatorvesting.ValidatorVestingAccount) | ||||
| 	if !ok { | ||||
| 		return sdkerrors.Wrapf(types.ErrInvalidAccountType, "owner account must be validator vesting account %s", owner) | ||||
| 	} | ||||
| 
 | ||||
| 	multiplier, found := k.GetMultiplier(ctx, multiplierName) | ||||
| 	if !found { | ||||
| 		return sdkerrors.Wrapf(types.ErrInvalidMultiplier, string(multiplierName)) | ||||
| 	} | ||||
| 
 | ||||
| 	claimEnd := k.GetClaimEnd(ctx) | ||||
| 
 | ||||
| 	if ctx.BlockTime().After(claimEnd) { | ||||
| 		return sdkerrors.Wrapf(types.ErrClaimExpired, "block time %s > claim end time %s", ctx.BlockTime(), claimEnd) | ||||
| 	} | ||||
| 
 | ||||
| 	claim, err := k.SynchronizeUSDXMintingClaim(ctx, claim) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	rewardAmount := claim.Reward.Amount.ToDec().Mul(multiplier.Factor).RoundInt() | ||||
| 	if rewardAmount.IsZero() { | ||||
| 		return types.ErrZeroClaim | ||||
| 	} | ||||
| 	rewardCoin := sdk.NewCoin(claim.Reward.Denom, rewardAmount) | ||||
| 	length, err := k.GetPeriodLength(ctx, multiplier) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	err = k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, receiver, sdk.NewCoins(rewardCoin), length) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	k.ZeroUSDXMintingClaim(ctx, claim) | ||||
| 
 | ||||
| 	ctx.EventManager().EmitEvent( | ||||
| 		sdk.NewEvent( | ||||
| 			types.EventTypeClaim, | ||||
| 			sdk.NewAttribute(types.AttributeKeyClaimedBy, claim.GetOwner().String()), | ||||
| 			sdk.NewAttribute(types.AttributeKeyClaimAmount, claim.GetReward().String()), | ||||
| 			sdk.NewAttribute(types.AttributeKeyClaimAmount, claim.GetType()), | ||||
| 		), | ||||
| 	) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // ClaimHardReward sends the reward amount to the input address and zero's out the claim in the store
 | ||||
| func (k Keeper) ClaimHardReward(ctx sdk.Context, addr sdk.AccAddress, multiplierName types.MultiplierName) error { | ||||
| 	_, found := k.GetHardLiquidityProviderClaim(ctx, addr) | ||||
| @ -133,6 +193,74 @@ func (k Keeper) ClaimHardReward(ctx sdk.Context, addr sdk.AccAddress, multiplier | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // ClaimHardReward sends the reward amount to the input address and zero's out the claim in the store
 | ||||
| func (k Keeper) ClaimHardRewardVVesting(ctx sdk.Context, owner, receiver sdk.AccAddress, multiplierName types.MultiplierName) error { | ||||
| 	_, found := k.GetHardLiquidityProviderClaim(ctx, owner) | ||||
| 	if !found { | ||||
| 		return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", owner) | ||||
| 	} | ||||
| 
 | ||||
| 	acc := k.accountKeeper.GetAccount(ctx, owner) | ||||
| 	if acc == nil { | ||||
| 		return sdkerrors.Wrapf(types.ErrAccountNotFound, "address not found: %s", owner) | ||||
| 	} | ||||
| 	_, ok := acc.(*validatorvesting.ValidatorVestingAccount) | ||||
| 	if !ok { | ||||
| 		return sdkerrors.Wrapf(types.ErrInvalidAccountType, "owner account must be validator vesting account %s", owner) | ||||
| 	} | ||||
| 
 | ||||
| 	multiplier, found := k.GetMultiplier(ctx, multiplierName) | ||||
| 	if !found { | ||||
| 		return sdkerrors.Wrapf(types.ErrInvalidMultiplier, string(multiplierName)) | ||||
| 	} | ||||
| 
 | ||||
| 	claimEnd := k.GetClaimEnd(ctx) | ||||
| 
 | ||||
| 	if ctx.BlockTime().After(claimEnd) { | ||||
| 		return sdkerrors.Wrapf(types.ErrClaimExpired, "block time %s > claim end time %s", ctx.BlockTime(), claimEnd) | ||||
| 	} | ||||
| 
 | ||||
| 	k.SynchronizeHardLiquidityProviderClaim(ctx, owner) | ||||
| 
 | ||||
| 	claim, found := k.GetHardLiquidityProviderClaim(ctx, owner) | ||||
| 	if !found { | ||||
| 		return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", owner) | ||||
| 	} | ||||
| 
 | ||||
| 	var rewardCoins sdk.Coins | ||||
| 	for _, coin := range claim.Reward { | ||||
| 		rewardAmount := coin.Amount.ToDec().Mul(multiplier.Factor).RoundInt() | ||||
| 		if rewardAmount.IsZero() { | ||||
| 			continue | ||||
| 		} | ||||
| 		rewardCoins = append(rewardCoins, sdk.NewCoin(coin.Denom, rewardAmount)) | ||||
| 	} | ||||
| 	if rewardCoins.IsZero() { | ||||
| 		return types.ErrZeroClaim | ||||
| 	} | ||||
| 	length, err := k.GetPeriodLength(ctx, multiplier) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	err = k.SendTimeLockedCoinsToAccount(ctx, types.IncentiveMacc, receiver, rewardCoins, length) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	k.ZeroHardLiquidityProviderClaim(ctx, claim) | ||||
| 
 | ||||
| 	ctx.EventManager().EmitEvent( | ||||
| 		sdk.NewEvent( | ||||
| 			types.EventTypeClaim, | ||||
| 			sdk.NewAttribute(types.AttributeKeyClaimedBy, claim.GetOwner().String()), | ||||
| 			sdk.NewAttribute(types.AttributeKeyClaimAmount, claim.GetReward().String()), | ||||
| 			sdk.NewAttribute(types.AttributeKeyClaimType, claim.GetType()), | ||||
| 		), | ||||
| 	) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SendTimeLockedCoinsToAccount sends time-locked coins from the input module account to the recipient. If the recipients account is not a vesting account and the input length is greater than zero, the recipient account is converted to a periodic vesting account and the coins are added to the vesting balance as a vesting period with the input length.
 | ||||
| func (k Keeper) SendTimeLockedCoinsToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins, length int64) error { | ||||
| 	macc := k.supplyKeeper.GetModuleAccount(ctx, senderModule) | ||||
|  | ||||
| @ -155,6 +155,156 @@ func (suite *KeeperTestSuite) TestPayoutUSDXMintingClaim() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) TestPayoutUSDXMintingClaimVVesting() { | ||||
| 	type args struct { | ||||
| 		ctype                    string | ||||
| 		rewardsPerSecond         sdk.Coin | ||||
| 		initialTime              time.Time | ||||
| 		initialCollateral        sdk.Coin | ||||
| 		initialPrincipal         sdk.Coin | ||||
| 		multipliers              types.Multipliers | ||||
| 		multiplier               types.MultiplierName | ||||
| 		timeElapsed              int | ||||
| 		expectedBalance          sdk.Coins | ||||
| 		expectedPeriods          vesting.Periods | ||||
| 		isPeriodicVestingAccount bool | ||||
| 	} | ||||
| 	type errArgs struct { | ||||
| 		expectPass bool | ||||
| 		contains   string | ||||
| 	} | ||||
| 	type test struct { | ||||
| 		name    string | ||||
| 		args    args | ||||
| 		errArgs errArgs | ||||
| 	} | ||||
| 	testCases := []test{ | ||||
| 		{ | ||||
| 			"valid 1 day", | ||||
| 			args{ | ||||
| 				ctype:                    "bnb-a", | ||||
| 				rewardsPerSecond:         c("ukava", 122354), | ||||
| 				initialTime:              time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), | ||||
| 				initialCollateral:        c("bnb", 1000000000000), | ||||
| 				initialPrincipal:         c("usdx", 10000000000), | ||||
| 				multipliers:              types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				multiplier:               types.MultiplierName("large"), | ||||
| 				timeElapsed:              86400, | ||||
| 				expectedBalance:          cs(c("ukava", 11571385600)), | ||||
| 				expectedPeriods:          vesting.Periods{vesting.Period{Length: 32918400, Amount: cs(c("ukava", 10571385600))}}, | ||||
| 				isPeriodicVestingAccount: true, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: true, | ||||
| 				contains:   "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"invalid zero rewards", | ||||
| 			args{ | ||||
| 				ctype:                    "bnb-a", | ||||
| 				rewardsPerSecond:         c("ukava", 0), | ||||
| 				initialTime:              time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), | ||||
| 				initialCollateral:        c("bnb", 1000000000000), | ||||
| 				initialPrincipal:         c("usdx", 10000000000), | ||||
| 				multipliers:              types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				multiplier:               types.MultiplierName("large"), | ||||
| 				timeElapsed:              86400, | ||||
| 				expectedBalance:          cs(), | ||||
| 				expectedPeriods:          vesting.Periods{}, | ||||
| 				isPeriodicVestingAccount: false, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: false, | ||||
| 				contains:   "claim amount rounds to zero", | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(tc.name, func() { | ||||
| 			suite.SetupWithGenState() | ||||
| 			suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime) | ||||
| 
 | ||||
| 			// setup incentive state
 | ||||
| 			params := types.NewParams( | ||||
| 				types.RewardPeriods{types.NewRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)}, | ||||
| 				types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))}, | ||||
| 				types.MultiRewardPeriods{types.NewMultiRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), cs(tc.args.rewardsPerSecond))}, | ||||
| 				types.RewardPeriods{types.NewRewardPeriod(true, tc.args.ctype, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond)}, | ||||
| 				tc.args.multipliers, | ||||
| 				tc.args.initialTime.Add(time.Hour*24*365*5), | ||||
| 			) | ||||
| 			suite.keeper.SetParams(suite.ctx, params) | ||||
| 			suite.keeper.SetPreviousUSDXMintingAccrualTime(suite.ctx, tc.args.ctype, tc.args.initialTime) | ||||
| 			suite.keeper.SetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype, sdk.ZeroDec()) | ||||
| 
 | ||||
| 			// sets addrs[2] to be a validator vesting account
 | ||||
| 			ak := suite.app.GetAccountKeeper() | ||||
| 			acc := ak.GetAccount(suite.ctx, suite.addrs[2]) | ||||
| 			bacc := auth.NewBaseAccount(acc.GetAddress(), acc.GetCoins(), acc.GetPubKey(), acc.GetAccountNumber(), acc.GetSequence()) | ||||
| 			bva, err2 := vesting.NewBaseVestingAccount(bacc, cs(c("ukava", 400)), suite.ctx.BlockTime().Unix()+16) | ||||
| 			suite.Require().NoError(err2) | ||||
| 			periods := vesting.Periods{ | ||||
| 				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))}, | ||||
| 				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))}, | ||||
| 				vesting.Period{Length: int64(8), Amount: cs(c("ukava", 100))}, | ||||
| 				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))}, | ||||
| 			} | ||||
| 			vva := validatorvesting.NewValidatorVestingAccountRaw(bva, suite.ctx.BlockTime().Unix(), periods, sdk.ConsAddress{}, nil, 90) | ||||
| 			ak.SetAccount(suite.ctx, vva) | ||||
| 
 | ||||
| 			// setup account state
 | ||||
| 			sk := suite.app.GetSupplyKeeper() | ||||
| 			err := sk.MintCoins(suite.ctx, cdptypes.ModuleName, sdk.NewCoins(tc.args.initialCollateral)) | ||||
| 			suite.Require().NoError(err) | ||||
| 			err = sk.SendCoinsFromModuleToAccount(suite.ctx, cdptypes.ModuleName, suite.addrs[2], sdk.NewCoins(tc.args.initialCollateral)) | ||||
| 			suite.Require().NoError(err) | ||||
| 
 | ||||
| 			// setup kavadist state
 | ||||
| 			err = sk.MintCoins(suite.ctx, kavadist.ModuleName, cs(c("ukava", 1000000000000))) | ||||
| 			suite.Require().NoError(err) | ||||
| 
 | ||||
| 			// setup cdp state
 | ||||
| 			cdpKeeper := suite.app.GetCDPKeeper() | ||||
| 			err = cdpKeeper.AddCdp(suite.ctx, suite.addrs[2], tc.args.initialCollateral, tc.args.initialPrincipal, tc.args.ctype) | ||||
| 			suite.Require().NoError(err) | ||||
| 
 | ||||
| 			claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[2]) | ||||
| 			suite.Require().True(found) | ||||
| 			suite.Require().Equal(sdk.ZeroDec(), claim.RewardIndexes[0].RewardFactor) | ||||
| 
 | ||||
| 			updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * tc.args.timeElapsed)) | ||||
| 			suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime) | ||||
| 			rewardPeriod, found := suite.keeper.GetUSDXMintingRewardPeriod(suite.ctx, tc.args.ctype) | ||||
| 			suite.Require().True(found) | ||||
| 			err = suite.keeper.AccumulateUSDXMintingRewards(suite.ctx, rewardPeriod) | ||||
| 			suite.Require().NoError(err) | ||||
| 
 | ||||
| 			err = suite.keeper.ClaimUSDXMintingRewardVVesting(suite.ctx, suite.addrs[2], suite.addrs[0], tc.args.multiplier) | ||||
| 
 | ||||
| 			if tc.errArgs.expectPass { | ||||
| 				suite.Require().NoError(err) | ||||
| 				ak := suite.app.GetAccountKeeper() | ||||
| 				acc := ak.GetAccount(suite.ctx, suite.addrs[0]) | ||||
| 				suite.Require().Equal(tc.args.expectedBalance, acc.GetCoins()) // TODO check balance change to decouple from initialized account balance.
 | ||||
| 
 | ||||
| 				if tc.args.isPeriodicVestingAccount { | ||||
| 					vacc, ok := acc.(*vesting.PeriodicVestingAccount) | ||||
| 					suite.Require().True(ok) | ||||
| 					suite.Require().Equal(tc.args.expectedPeriods, vacc.VestingPeriods) | ||||
| 				} | ||||
| 
 | ||||
| 				claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[2]) | ||||
| 				suite.Require().True(found) | ||||
| 				suite.Require().Equal(c("ukava", 0), claim.Reward) | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 				suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) TestPayoutHardLiquidityProviderClaim() { | ||||
| 	type args struct { | ||||
| 		deposit                  sdk.Coins | ||||
| @ -431,6 +581,296 @@ func (suite *KeeperTestSuite) TestPayoutHardLiquidityProviderClaim() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) TestPayoutHardLiquidityProviderClaimVVesting() { | ||||
| 	type args struct { | ||||
| 		deposit                  sdk.Coins | ||||
| 		borrow                   sdk.Coins | ||||
| 		rewardsPerSecond         sdk.Coins | ||||
| 		initialTime              time.Time | ||||
| 		multipliers              types.Multipliers | ||||
| 		multiplier               types.MultiplierName | ||||
| 		timeElapsed              int64 | ||||
| 		expectedRewards          sdk.Coins | ||||
| 		expectedPeriods          vesting.Periods | ||||
| 		isPeriodicVestingAccount bool | ||||
| 	} | ||||
| 	type errArgs struct { | ||||
| 		expectPass bool | ||||
| 		contains   string | ||||
| 	} | ||||
| 	type test struct { | ||||
| 		name    string | ||||
| 		args    args | ||||
| 		errArgs errArgs | ||||
| 	} | ||||
| 	testCases := []test{ | ||||
| 		{ | ||||
| 			"single reward denom: valid 1 day", | ||||
| 			args{ | ||||
| 				deposit:                  cs(c("bnb", 10000000000)), | ||||
| 				borrow:                   cs(c("bnb", 5000000000)), | ||||
| 				rewardsPerSecond:         cs(c("hard", 122354)), | ||||
| 				initialTime:              time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), | ||||
| 				multipliers:              types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				multiplier:               types.MultiplierName("large"), | ||||
| 				timeElapsed:              86400, | ||||
| 				expectedRewards:          cs(c("hard", 21142771200)), // 10571385600 (deposit reward) + 10571385600 (borrow reward)
 | ||||
| 				expectedPeriods:          vesting.Periods{vesting.Period{Length: 32918400, Amount: cs(c("hard", 21142771200))}}, | ||||
| 				isPeriodicVestingAccount: true, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: true, | ||||
| 				contains:   "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"single reward denom: valid 10 days", | ||||
| 			args{ | ||||
| 				deposit:                  cs(c("bnb", 10000000000)), | ||||
| 				borrow:                   cs(c("bnb", 5000000000)), | ||||
| 				rewardsPerSecond:         cs(c("hard", 122354)), | ||||
| 				initialTime:              time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), | ||||
| 				multipliers:              types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				multiplier:               types.MultiplierName("large"), | ||||
| 				timeElapsed:              864000, | ||||
| 				expectedRewards:          cs(c("hard", 211427712000)), // 105713856000 (deposit reward) + 105713856000 (borrow reward)
 | ||||
| 				expectedPeriods:          vesting.Periods{vesting.Period{Length: 32140800, Amount: cs(c("hard", 211427712000))}}, | ||||
| 				isPeriodicVestingAccount: true, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: true, | ||||
| 				contains:   "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"invalid zero rewards", | ||||
| 			args{ | ||||
| 				deposit:                  cs(c("bnb", 10000000000)), | ||||
| 				borrow:                   cs(c("bnb", 5000000000)), | ||||
| 				rewardsPerSecond:         cs(c("hard", 0)), | ||||
| 				initialTime:              time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), | ||||
| 				multipliers:              types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				multiplier:               types.MultiplierName("large"), | ||||
| 				timeElapsed:              86400, | ||||
| 				expectedRewards:          cs(c("hard", 0)), | ||||
| 				expectedPeriods:          vesting.Periods{}, | ||||
| 				isPeriodicVestingAccount: false, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: false, | ||||
| 				contains:   "claim amount rounds to zero", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"multiple reward denoms: valid 1 day", | ||||
| 			args{ | ||||
| 				deposit:                  cs(c("bnb", 10000000000)), | ||||
| 				borrow:                   cs(c("bnb", 5000000000)), | ||||
| 				rewardsPerSecond:         cs(c("hard", 122354), c("ukava", 122354)), | ||||
| 				initialTime:              time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), | ||||
| 				multipliers:              types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				multiplier:               types.MultiplierName("large"), | ||||
| 				timeElapsed:              86400, | ||||
| 				expectedRewards:          cs(c("hard", 21142771200), c("ukava", 21142771200)), // 10571385600 (deposit reward) + 10571385600 (borrow reward)
 | ||||
| 				expectedPeriods:          vesting.Periods{vesting.Period{Length: 32918400, Amount: cs(c("hard", 21142771200), c("ukava", 21142771200))}}, | ||||
| 				isPeriodicVestingAccount: true, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: true, | ||||
| 				contains:   "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"multiple reward denoms: valid 10 days", | ||||
| 			args{ | ||||
| 				deposit:                  cs(c("bnb", 10000000000)), | ||||
| 				borrow:                   cs(c("bnb", 5000000000)), | ||||
| 				rewardsPerSecond:         cs(c("hard", 122354), c("ukava", 122354)), | ||||
| 				initialTime:              time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), | ||||
| 				multipliers:              types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				multiplier:               types.MultiplierName("large"), | ||||
| 				timeElapsed:              864000, | ||||
| 				expectedRewards:          cs(c("hard", 211427712000), c("ukava", 211427712000)), // 105713856000 (deposit reward) + 105713856000 (borrow reward)
 | ||||
| 				expectedPeriods:          vesting.Periods{vesting.Period{Length: 32140800, Amount: cs(c("hard", 211427712000), c("ukava", 211427712000))}}, | ||||
| 				isPeriodicVestingAccount: true, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: true, | ||||
| 				contains:   "", | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"multiple reward denoms with different rewards per second: valid 1 day", | ||||
| 			args{ | ||||
| 				deposit:                  cs(c("bnb", 10000000000)), | ||||
| 				borrow:                   cs(c("bnb", 5000000000)), | ||||
| 				rewardsPerSecond:         cs(c("hard", 122354), c("ukava", 222222)), | ||||
| 				initialTime:              time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC), | ||||
| 				multipliers:              types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				multiplier:               types.MultiplierName("large"), | ||||
| 				timeElapsed:              86400, | ||||
| 				expectedRewards:          cs(c("hard", 21142771200), c("ukava", 38399961600)), | ||||
| 				expectedPeriods:          vesting.Periods{vesting.Period{Length: 32918400, Amount: cs(c("hard", 21142771200), c("ukava", 38399961600))}}, | ||||
| 				isPeriodicVestingAccount: true, | ||||
| 			}, | ||||
| 			errArgs{ | ||||
| 				expectPass: true, | ||||
| 				contains:   "", | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(tc.name, func() { | ||||
| 			suite.SetupWithGenState() | ||||
| 			suite.ctx = suite.ctx.WithBlockTime(tc.args.initialTime) | ||||
| 
 | ||||
| 			// setup kavadist state
 | ||||
| 			sk := suite.app.GetSupplyKeeper() | ||||
| 			err := sk.MintCoins(suite.ctx, kavadist.ModuleName, cs(c("hard", 1000000000000000000), c("ukava", 1000000000000000000))) | ||||
| 			suite.Require().NoError(err) | ||||
| 
 | ||||
| 			// Set up generic reward periods
 | ||||
| 			var multiRewardPeriods types.MultiRewardPeriods | ||||
| 			var rewardPeriods types.RewardPeriods | ||||
| 			for _, coin := range tc.args.deposit { | ||||
| 				if len(tc.args.rewardsPerSecond) > 0 { | ||||
| 					rewardPeriod := types.NewRewardPeriod(true, coin.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond[0]) | ||||
| 					rewardPeriods = append(rewardPeriods, rewardPeriod) | ||||
| 				} | ||||
| 				multiRewardPeriod := types.NewMultiRewardPeriod(true, coin.Denom, tc.args.initialTime, tc.args.initialTime.Add(time.Hour*24*365*4), tc.args.rewardsPerSecond) | ||||
| 				multiRewardPeriods = append(multiRewardPeriods, multiRewardPeriod) | ||||
| 			} | ||||
| 
 | ||||
| 			// Set up generic reward periods
 | ||||
| 			params := types.NewParams( | ||||
| 				rewardPeriods, multiRewardPeriods, multiRewardPeriods, rewardPeriods, | ||||
| 				types.Multipliers{types.NewMultiplier(types.MultiplierName("small"), 1, d("0.25")), types.NewMultiplier(types.MultiplierName("large"), 12, d("1.0"))}, | ||||
| 				tc.args.initialTime.Add(time.Hour*24*365*5), | ||||
| 			) | ||||
| 			suite.keeper.SetParams(suite.ctx, params) | ||||
| 
 | ||||
| 			// Set each denom's previous accrual time and supply reward factor
 | ||||
| 			if len(tc.args.rewardsPerSecond) > 0 { | ||||
| 				for _, coin := range tc.args.deposit { | ||||
| 					suite.keeper.SetPreviousHardSupplyRewardAccrualTime(suite.ctx, coin.Denom, tc.args.initialTime) | ||||
| 					var rewardIndexes types.RewardIndexes | ||||
| 					for _, rewardCoin := range tc.args.rewardsPerSecond { | ||||
| 						rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec()) | ||||
| 						rewardIndexes = append(rewardIndexes, rewardIndex) | ||||
| 					} | ||||
| 					suite.keeper.SetHardSupplyRewardIndexes(suite.ctx, coin.Denom, rewardIndexes) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// Set each denom's previous accrual time and borrow reward factor
 | ||||
| 			if len(tc.args.rewardsPerSecond) > 0 { | ||||
| 				for _, coin := range tc.args.borrow { | ||||
| 					suite.keeper.SetPreviousHardBorrowRewardAccrualTime(suite.ctx, coin.Denom, tc.args.initialTime) | ||||
| 					var rewardIndexes types.RewardIndexes | ||||
| 					for _, rewardCoin := range tc.args.rewardsPerSecond { | ||||
| 						rewardIndex := types.NewRewardIndex(rewardCoin.Denom, sdk.ZeroDec()) | ||||
| 						rewardIndexes = append(rewardIndexes, rewardIndex) | ||||
| 					} | ||||
| 					suite.keeper.SetHardBorrowRewardIndexes(suite.ctx, coin.Denom, rewardIndexes) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// sets addrs[3] to be a validator vesting account
 | ||||
| 			ak := suite.app.GetAccountKeeper() | ||||
| 			acc := ak.GetAccount(suite.ctx, suite.addrs[3]) | ||||
| 			bacc := auth.NewBaseAccount(acc.GetAddress(), acc.GetCoins(), acc.GetPubKey(), acc.GetAccountNumber(), acc.GetSequence()) | ||||
| 			bva, err2 := vesting.NewBaseVestingAccount(bacc, cs(c("ukava", 400)), suite.ctx.BlockTime().Unix()+16) | ||||
| 			suite.Require().NoError(err2) | ||||
| 			periods := vesting.Periods{ | ||||
| 				vesting.Period{Length: int64(1), Amount: cs(c("ukava", 100))}, | ||||
| 				vesting.Period{Length: int64(2), Amount: cs(c("ukava", 100))}, | ||||
| 				vesting.Period{Length: int64(8), Amount: cs(c("ukava", 100))}, | ||||
| 				vesting.Period{Length: int64(5), Amount: cs(c("ukava", 100))}, | ||||
| 			} | ||||
| 			vva := validatorvesting.NewValidatorVestingAccountRaw(bva, suite.ctx.BlockTime().Unix(), periods, sdk.ConsAddress{}, nil, 90) | ||||
| 			ak.SetAccount(suite.ctx, vva) | ||||
| 
 | ||||
| 			hardKeeper := suite.app.GetHardKeeper() | ||||
| 			userAddr := suite.addrs[3] | ||||
| 
 | ||||
| 			// User deposits and borrows
 | ||||
| 			err = hardKeeper.Deposit(suite.ctx, userAddr, tc.args.deposit) | ||||
| 			suite.Require().NoError(err) | ||||
| 			err = hardKeeper.Borrow(suite.ctx, userAddr, tc.args.borrow) | ||||
| 			suite.Require().NoError(err) | ||||
| 
 | ||||
| 			// Check that Hard hooks initialized a HardLiquidityProviderClaim that has 0 rewards
 | ||||
| 			claim, found := suite.keeper.GetHardLiquidityProviderClaim(suite.ctx, suite.addrs[3]) | ||||
| 			suite.Require().True(found) | ||||
| 			for _, coin := range tc.args.deposit { | ||||
| 				suite.Require().Equal(sdk.ZeroInt(), claim.Reward.AmountOf(coin.Denom)) | ||||
| 			} | ||||
| 
 | ||||
| 			// Set up future runtime context
 | ||||
| 			runAtTime := time.Unix(suite.ctx.BlockTime().Unix()+(tc.args.timeElapsed), 0) | ||||
| 			runCtx := suite.ctx.WithBlockTime(runAtTime) | ||||
| 
 | ||||
| 			// Run Hard begin blocker
 | ||||
| 			hard.BeginBlocker(runCtx, suite.hardKeeper) | ||||
| 
 | ||||
| 			// Accumulate supply rewards for each deposit denom
 | ||||
| 			for _, coin := range tc.args.deposit { | ||||
| 				rewardPeriod, found := suite.keeper.GetHardSupplyRewardPeriods(runCtx, coin.Denom) | ||||
| 				suite.Require().True(found) | ||||
| 				err = suite.keeper.AccumulateHardSupplyRewards(runCtx, rewardPeriod) | ||||
| 				suite.Require().NoError(err) | ||||
| 			} | ||||
| 
 | ||||
| 			// Accumulate borrow rewards for each deposit denom
 | ||||
| 			for _, coin := range tc.args.borrow { | ||||
| 				rewardPeriod, found := suite.keeper.GetHardBorrowRewardPeriods(runCtx, coin.Denom) | ||||
| 				suite.Require().True(found) | ||||
| 				err = suite.keeper.AccumulateHardBorrowRewards(runCtx, rewardPeriod) | ||||
| 				suite.Require().NoError(err) | ||||
| 			} | ||||
| 
 | ||||
| 			// Sync hard supply rewards
 | ||||
| 			deposit, found := suite.hardKeeper.GetDeposit(suite.ctx, suite.addrs[3]) | ||||
| 			suite.Require().True(found) | ||||
| 			suite.keeper.SynchronizeHardSupplyReward(suite.ctx, deposit) | ||||
| 
 | ||||
| 			// Sync hard borrow rewards
 | ||||
| 			borrow, found := suite.hardKeeper.GetBorrow(suite.ctx, suite.addrs[3]) | ||||
| 			suite.Require().True(found) | ||||
| 			suite.keeper.SynchronizeHardBorrowReward(suite.ctx, borrow) | ||||
| 
 | ||||
| 			// Fetch pre-claim balances
 | ||||
| 			preClaimAcc := ak.GetAccount(runCtx, suite.addrs[2]) | ||||
| 
 | ||||
| 			err = suite.keeper.ClaimHardRewardVVesting(runCtx, suite.addrs[3], suite.addrs[2], tc.args.multiplier) | ||||
| 			if tc.errArgs.expectPass { | ||||
| 				suite.Require().NoError(err) | ||||
| 
 | ||||
| 				// Check that user's balance has increased by expected reward amount
 | ||||
| 				postClaimAcc := ak.GetAccount(suite.ctx, suite.addrs[2]) | ||||
| 				suite.Require().Equal(preClaimAcc.GetCoins().Add(tc.args.expectedRewards...), postClaimAcc.GetCoins()) | ||||
| 
 | ||||
| 				if tc.args.isPeriodicVestingAccount { | ||||
| 					vacc, ok := postClaimAcc.(*vesting.PeriodicVestingAccount) | ||||
| 					suite.Require().True(ok) | ||||
| 					suite.Require().Equal(tc.args.expectedPeriods, vacc.VestingPeriods) | ||||
| 				} | ||||
| 
 | ||||
| 				// Check that each claim reward coin's amount has been reset to 0
 | ||||
| 				claim, found := suite.keeper.GetHardLiquidityProviderClaim(runCtx, suite.addrs[3]) | ||||
| 				suite.Require().True(found) | ||||
| 				for _, claimRewardCoin := range claim.Reward { | ||||
| 					suite.Require().Equal(c(claimRewardCoin.Denom, 0), claimRewardCoin) | ||||
| 				} | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 				suite.Require().True(strings.Contains(err.Error(), tc.errArgs.contains)) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *KeeperTestSuite) TestSendCoinsToPeriodicVestingAccount() { | ||||
| 	type accountArgs struct { | ||||
| 		periods          vesting.Periods | ||||
|  | ||||
| @ -21,4 +21,6 @@ func RegisterCodec(cdc *codec.Codec) { | ||||
| 	// Register msgs
 | ||||
| 	cdc.RegisterConcrete(MsgClaimUSDXMintingReward{}, "incentive/MsgClaimUSDXMintingReward", nil) | ||||
| 	cdc.RegisterConcrete(MsgClaimHardReward{}, "incentive/MsgClaimHardReward", nil) | ||||
| 	cdc.RegisterConcrete(MsgClaimUSDXMintingRewardVVesting{}, "incentive/MsgClaimUSDXRewardVVesting", nil) | ||||
| 	cdc.RegisterConcrete(MsgClaimHardRewardVVesting{}, "incentive/MsgClaimHardRewardVVesting", nil) | ||||
| } | ||||
|  | ||||
| @ -10,6 +10,8 @@ import ( | ||||
| // ensure Msg interface compliance at compile time
 | ||||
| var _ sdk.Msg = &MsgClaimUSDXMintingReward{} | ||||
| var _ sdk.Msg = &MsgClaimHardReward{} | ||||
| var _ sdk.Msg = &MsgClaimHardRewardVVesting{} | ||||
| var _ sdk.Msg = &MsgClaimUSDXMintingRewardVVesting{} | ||||
| 
 | ||||
| // MsgClaimUSDXMintingReward message type used to claim USDX minting rewards
 | ||||
| type MsgClaimUSDXMintingReward struct { | ||||
| @ -50,6 +52,52 @@ func (msg MsgClaimUSDXMintingReward) GetSigners() []sdk.AccAddress { | ||||
| 	return []sdk.AccAddress{msg.Sender} | ||||
| } | ||||
| 
 | ||||
| // MsgClaimUSDXMintingRewardVVesting message type used to claim USDX minting rewards for validator vesting accounts
 | ||||
| type MsgClaimUSDXMintingRewardVVesting struct { | ||||
| 	Sender         sdk.AccAddress `json:"sender" yaml:"sender"` | ||||
| 	Receiver       sdk.AccAddress `json:"receiver" yaml:"receiver"` | ||||
| 	MultiplierName string         `json:"multiplier_name" yaml:"multiplier_name"` | ||||
| } | ||||
| 
 | ||||
| // NewMsgClaimUSDXMintingRewardVVesting returns a new MsgClaimUSDXMintingReward.
 | ||||
| func NewMsgClaimUSDXMintingRewardVVesting(sender, receiver sdk.AccAddress, multiplierName string) MsgClaimUSDXMintingRewardVVesting { | ||||
| 	return MsgClaimUSDXMintingRewardVVesting{ | ||||
| 		Sender:         sender, | ||||
| 		Receiver:       receiver, | ||||
| 		MultiplierName: multiplierName, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Route return the message type used for routing the message.
 | ||||
| func (msg MsgClaimUSDXMintingRewardVVesting) Route() string { return RouterKey } | ||||
| 
 | ||||
| // Type returns a human-readable string for the message, intended for utilization within tags.
 | ||||
| func (msg MsgClaimUSDXMintingRewardVVesting) Type() string { | ||||
| 	return "claim_usdx_minting_reward_vvesting" | ||||
| } | ||||
| 
 | ||||
| // ValidateBasic does a simple validation check that doesn't require access to state.
 | ||||
| func (msg MsgClaimUSDXMintingRewardVVesting) ValidateBasic() error { | ||||
| 	if msg.Sender.Empty() { | ||||
| 		return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") | ||||
| 	} | ||||
| 	if msg.Receiver.Empty() { | ||||
| 		return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be empty") | ||||
| 	} | ||||
| 	return MultiplierName(strings.ToLower(msg.MultiplierName)).IsValid() | ||||
| } | ||||
| 
 | ||||
| // GetSignBytes gets the canonical byte representation of the Msg.
 | ||||
| func (msg MsgClaimUSDXMintingRewardVVesting) GetSignBytes() []byte { | ||||
| 	bz := ModuleCdc.MustMarshalJSON(msg) | ||||
| 	return sdk.MustSortJSON(bz) | ||||
| } | ||||
| 
 | ||||
| // GetSigners returns the addresses of signers that must sign.
 | ||||
| func (msg MsgClaimUSDXMintingRewardVVesting) GetSigners() []sdk.AccAddress { | ||||
| 	return []sdk.AccAddress{msg.Sender} | ||||
| } | ||||
| 
 | ||||
| // MsgClaimHardReward message type used to claim Hard liquidity provider rewards
 | ||||
| type MsgClaimHardReward struct { | ||||
| 	Sender         sdk.AccAddress `json:"sender" yaml:"sender"` | ||||
| @ -90,3 +138,49 @@ func (msg MsgClaimHardReward) GetSignBytes() []byte { | ||||
| func (msg MsgClaimHardReward) GetSigners() []sdk.AccAddress { | ||||
| 	return []sdk.AccAddress{msg.Sender} | ||||
| } | ||||
| 
 | ||||
| // MsgClaimHardRewardVVesting message type used to claim Hard liquidity provider rewards for validator vesting accounts
 | ||||
| type MsgClaimHardRewardVVesting struct { | ||||
| 	Sender         sdk.AccAddress `json:"sender" yaml:"sender"` | ||||
| 	Receiver       sdk.AccAddress `json:"receiver" yaml:"receiver"` | ||||
| 	MultiplierName string         `json:"multiplier_name" yaml:"multiplier_name"` | ||||
| } | ||||
| 
 | ||||
| // NewMsgClaimHardRewardVVesting returns a new MsgClaimHardReward.
 | ||||
| func NewMsgClaimHardRewardVVesting(sender, receiver sdk.AccAddress, multiplierName string) MsgClaimHardRewardVVesting { | ||||
| 	return MsgClaimHardRewardVVesting{ | ||||
| 		Sender:         sender, | ||||
| 		Receiver:       receiver, | ||||
| 		MultiplierName: multiplierName, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Route return the message type used for routing the message.
 | ||||
| func (msg MsgClaimHardRewardVVesting) Route() string { return RouterKey } | ||||
| 
 | ||||
| // Type returns a human-readable string for the message, intended for utilization within tags.
 | ||||
| func (msg MsgClaimHardRewardVVesting) Type() string { | ||||
| 	return "claim_hard_reward_vvesting" | ||||
| } | ||||
| 
 | ||||
| // ValidateBasic does a simple validation check that doesn't require access to state.
 | ||||
| func (msg MsgClaimHardRewardVVesting) ValidateBasic() error { | ||||
| 	if msg.Sender.Empty() { | ||||
| 		return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be empty") | ||||
| 	} | ||||
| 	if msg.Receiver.Empty() { | ||||
| 		return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be empty") | ||||
| 	} | ||||
| 	return MultiplierName(strings.ToLower(msg.MultiplierName)).IsValid() | ||||
| } | ||||
| 
 | ||||
| // GetSignBytes gets the canonical byte representation of the Msg.
 | ||||
| func (msg MsgClaimHardRewardVVesting) GetSignBytes() []byte { | ||||
| 	bz := ModuleCdc.MustMarshalJSON(msg) | ||||
| 	return sdk.MustSortJSON(bz) | ||||
| } | ||||
| 
 | ||||
| // GetSigners returns the addresses of signers that must sign.
 | ||||
| func (msg MsgClaimHardRewardVVesting) GetSigners() []sdk.AccAddress { | ||||
| 	return []sdk.AccAddress{msg.Sender} | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Kevin Davis
						Kevin Davis