From e9eb5ea20cfcef84dfda786feda942581f7b279c Mon Sep 17 00:00:00 2001 From: Kevin Davis Date: Mon, 8 Feb 2021 13:47:29 -0700 Subject: [PATCH] genesis updates for incentive migration (#806) --- x/incentive/alias.go | 195 +++++---- x/incentive/genesis.go | 19 +- x/incentive/handler_test.go | 6 +- x/incentive/integration_test.go | 6 +- x/incentive/legacy/v0_13/types.go | 647 ++++++++++++++++++++++++++++++ x/incentive/types/genesis.go | 46 ++- x/incentive/types/genesis_test.go | 6 +- x/incentive/types/params.go | 3 +- 8 files changed, 830 insertions(+), 98 deletions(-) create mode 100644 x/incentive/legacy/v0_13/types.go diff --git a/x/incentive/alias.go b/x/incentive/alias.go index a321f67c..501614a2 100644 --- a/x/incentive/alias.go +++ b/x/incentive/alias.go @@ -8,29 +8,39 @@ import ( ) const ( - AttributeKeyClaimAmount = types.AttributeKeyClaimAmount - AttributeKeyClaimPeriod = types.AttributeKeyClaimPeriod - AttributeKeyClaimedBy = types.AttributeKeyClaimedBy - AttributeKeyRewardPeriod = types.AttributeKeyRewardPeriod - AttributeValueCategory = types.AttributeValueCategory - DefaultParamspace = types.DefaultParamspace - EventTypeClaim = types.EventTypeClaim - EventTypeClaimPeriod = types.EventTypeClaimPeriod - EventTypeClaimPeriodExpiry = types.EventTypeClaimPeriodExpiry - EventTypeRewardPeriod = types.EventTypeRewardPeriod - Large = types.Large - Medium = types.Medium - ModuleName = types.ModuleName - QuerierRoute = types.QuerierRoute - QueryGetClaimPeriods = types.QueryGetClaimPeriods - QueryGetRewards = types.QueryGetRewards - QueryGetParams = types.QueryGetParams - QueryGetRewardPeriods = types.QueryGetRewardPeriods - RestClaimCollateralType = types.RestClaimCollateralType - RestClaimOwner = types.RestClaimOwner - RouterKey = types.RouterKey - Small = types.Small - StoreKey = types.StoreKey + 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 ) var ( @@ -43,74 +53,103 @@ var ( GetTotalVestingPeriodLength = types.GetTotalVestingPeriodLength NewGenesisAccumulationTime = types.NewGenesisAccumulationTime NewGenesisState = types.NewGenesisState - NewMsgClaimUSDXMintingReward = types.NewMsgClaimUSDXMintingReward + NewHardLiquidityProviderClaim = types.NewHardLiquidityProviderClaim NewMsgClaimHardLiquidityProviderReward = types.NewMsgClaimHardLiquidityProviderReward + 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 - NewMultiRewardPeriod = types.NewMultiRewardPeriod NewUSDXMintingClaim = types.NewUSDXMintingClaim - NewHardLiquidityProviderClaim = types.NewHardLiquidityProviderClaim ParamKeyTable = types.ParamKeyTable RegisterCodec = types.RegisterCodec // variable aliases - PreviousUSDXMintingRewardAccrualTimeKeyPrefix = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix - USDXMintingClaimKeyPrefix = types.USDXMintingClaimKeyPrefix - DefaultActive = types.DefaultActive - DefaultClaimEnd = types.DefaultClaimEnd - DefaultClaims = types.DefaultClaims - DefaultGenesisAccumulationTimes = types.DefaultGenesisAccumulationTimes - DefaultMultipliers = types.DefaultMultipliers - DefaultRewardPeriods = types.DefaultRewardPeriods - DefaultMultiRewardPeriods = types.DefaultMultiRewardPeriods - ErrAccountNotFound = types.ErrAccountNotFound - ErrClaimExpired = types.ErrClaimExpired - ErrClaimNotFound = types.ErrClaimNotFound - ErrInsufficientModAccountBalance = types.ErrInsufficientModAccountBalance - ErrInvalidAccountType = types.ErrInvalidAccountType - ErrInvalidMultiplier = types.ErrInvalidMultiplier - ErrNoClaimsFound = types.ErrNoClaimsFound - ErrRewardPeriodNotFound = types.ErrRewardPeriodNotFound - ErrZeroClaim = types.ErrZeroClaim - GovDenom = types.GovDenom - IncentiveMacc = types.IncentiveMacc - KeyClaimEnd = types.KeyClaimEnd - KeyMultipliers = types.KeyMultipliers - KeyUSDXMintingRewardPeriods = types.KeyUSDXMintingRewardPeriods - ModuleCdc = types.ModuleCdc - PrincipalDenom = types.PrincipalDenom - USDXMintingRewardFactorKeyPrefix = types.USDXMintingRewardFactorKeyPrefix - USDXMintingRewardDenom = types.USDXMintingRewardDenom + 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 + ErrClaimNotFound = types.ErrClaimNotFound + ErrInsufficientModAccountBalance = types.ErrInsufficientModAccountBalance + ErrInvalidAccountType = types.ErrInvalidAccountType + ErrInvalidClaimType = types.ErrInvalidClaimType + ErrInvalidMultiplier = types.ErrInvalidMultiplier + ErrNoClaimsFound = types.ErrNoClaimsFound + ErrRewardPeriodNotFound = types.ErrRewardPeriodNotFound + ErrZeroClaim = types.ErrZeroClaim + GovDenom = types.GovDenom + HardBorrowRewardIndexesKeyPrefix = types.HardBorrowRewardIndexesKeyPrefix + HardDelegatorRewardFactorKeyPrefix = types.HardDelegatorRewardFactorKeyPrefix + HardLiquidityClaimKeyPrefix = types.HardLiquidityClaimKeyPrefix + HardLiquidityRewardDenom = types.HardLiquidityRewardDenom + HardSupplyRewardIndexesKeyPrefix = types.HardSupplyRewardIndexesKeyPrefix + IncentiveMacc = types.IncentiveMacc + KeyClaimEnd = types.KeyClaimEnd + KeyHardBorrowRewardPeriods = types.KeyHardBorrowRewardPeriods + KeyHardDelegatorRewardPeriods = types.KeyHardDelegatorRewardPeriods + KeyHardSupplyRewardPeriods = types.KeyHardSupplyRewardPeriods + KeyMultipliers = types.KeyMultipliers + KeyUSDXMintingRewardPeriods = types.KeyUSDXMintingRewardPeriods + ModuleCdc = types.ModuleCdc + PreviousHardBorrowRewardAccrualTimeKeyPrefix = types.PreviousHardBorrowRewardAccrualTimeKeyPrefix + PreviousHardDelegatorRewardAccrualTimeKeyPrefix = types.PreviousHardDelegatorRewardAccrualTimeKeyPrefix + PreviousHardSupplyRewardAccrualTimeKeyPrefix = types.PreviousHardSupplyRewardAccrualTimeKeyPrefix + PreviousUSDXMintingRewardAccrualTimeKeyPrefix = types.PreviousUSDXMintingRewardAccrualTimeKeyPrefix + PrincipalDenom = types.PrincipalDenom + USDXMintingClaimKeyPrefix = types.USDXMintingClaimKeyPrefix + USDXMintingRewardDenom = types.USDXMintingRewardDenom + USDXMintingRewardFactorKeyPrefix = types.USDXMintingRewardFactorKeyPrefix ) type ( - Hooks = keeper.Hooks - Keeper = keeper.Keeper - AccountKeeper = types.AccountKeeper - CDPHooks = types.CDPHooks - HARDHooks = types.HARDHooks - CdpKeeper = types.CdpKeeper - GenesisAccumulationTime = types.GenesisAccumulationTime - GenesisAccumulationTimes = types.GenesisAccumulationTimes - GenesisState = types.GenesisState - MsgClaimUSDXMintingReward = types.MsgClaimUSDXMintingReward - Multiplier = types.Multiplier - MultiplierName = types.MultiplierName - Multipliers = types.Multipliers - Params = types.Params - PostClaimReq = types.PostClaimReq - QueryRewardsParams = types.QueryRewardsParams - RewardIndex = types.RewardIndex - RewardIndexes = types.RewardIndexes - RewardPeriod = types.RewardPeriod - RewardPeriods = types.RewardPeriods - MultiRewardPeriod = types.MultiRewardPeriod - MultiRewardPeriods = types.MultiRewardPeriods - SupplyKeeper = types.SupplyKeeper - USDXMintingClaim = types.USDXMintingClaim - USDXMintingClaims = types.USDXMintingClaims + 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 + MsgClaimHardLiquidityProviderReward = types.MsgClaimHardLiquidityProviderReward + 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 + PostClaimReq = types.PostClaimReq + 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 ) diff --git a/x/incentive/genesis.go b/x/incentive/genesis.go index 1c19faec..857bad03 100644 --- a/x/incentive/genesis.go +++ b/x/incentive/genesis.go @@ -33,11 +33,23 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep // TODO: previous hard module accrual times/indexes should be set here - for _, gat := range gs.PreviousAccumulationTimes { + for _, gat := range gs.USDXAccumulationTimes { k.SetPreviousUSDXMintingAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) k.SetUSDXMintingRewardFactor(ctx, gat.CollateralType, gat.RewardFactor) } + for _, gat := range gs.HardSupplyAccumulationTimes { + k.SetPreviousHardSupplyRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) + } + + for _, gat := range gs.HardBorrowAccumulationTimes { + k.SetPreviousHardBorrowRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) + } + + for _, gat := range gs.HardDelegatorAccumulationTimes { + k.SetPreviousHardDelegatorRewardAccrualTime(ctx, gat.CollateralType, gat.PreviousAccumulationTime) + } + for _, claim := range gs.USDXMintingClaims { k.SetUSDXMintingClaim(ctx, claim) } @@ -48,7 +60,8 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, supplyKeeper types.SupplyKeep func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { params := k.GetParams(ctx) - claims := k.GetAllUSDXMintingClaims(ctx) + usdxClaims := k.GetAllUSDXMintingClaims(ctx) + hardClaims := k.GetAllHardLiquidityProviderClaims(ctx) var gats GenesisAccumulationTimes @@ -65,5 +78,5 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { gats = append(gats, gat) } - return types.NewGenesisState(params, gats, claims) + return types.NewGenesisState(params, gats, DefaultGenesisAccumulationTimes, DefaultGenesisAccumulationTimes, DefaultGenesisAccumulationTimes, usdxClaims, hardClaims) } diff --git a/x/incentive/handler_test.go b/x/incentive/handler_test.go index 6c5aaaee..b5bfa512 100644 --- a/x/incentive/handler_test.go +++ b/x/incentive/handler_test.go @@ -52,7 +52,11 @@ func (suite *HandlerTestSuite) SetupTest() { time.Date(2025, 12, 15, 14, 0, 0, 0, time.UTC), ), incentive.DefaultGenesisAccumulationTimes, - incentive.DefaultClaims, + incentive.DefaultGenesisAccumulationTimes, + incentive.DefaultGenesisAccumulationTimes, + incentive.DefaultGenesisAccumulationTimes, + incentive.DefaultUSDXClaims, + incentive.DefaultHardClaims, ) tApp.InitializeFromGenesisStates(authGS, app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(incentiveGS)}, NewCDPGenStateMulti(), NewPricefeedGenStateMulti()) diff --git a/x/incentive/integration_test.go b/x/incentive/integration_test.go index a6e68955..d551d498 100644 --- a/x/incentive/integration_test.go +++ b/x/incentive/integration_test.go @@ -166,7 +166,11 @@ func NewIncentiveGenState(previousAccumTime, endTime time.Time, rewardPeriods .. endTime, ), accumulationTimes, - incentive.USDXMintingClaims{}, + accumulationTimes, + accumulationTimes, + incentive.DefaultGenesisAccumulationTimes, + incentive.DefaultUSDXClaims, + incentive.DefaultHardClaims, ) return app.GenesisState{incentive.ModuleName: incentive.ModuleCdc.MustMarshalJSON(genesis)} } diff --git a/x/incentive/legacy/v0_13/types.go b/x/incentive/legacy/v0_13/types.go new file mode 100644 index 00000000..25b16e9b --- /dev/null +++ b/x/incentive/legacy/v0_13/types.go @@ -0,0 +1,647 @@ +package v0_13 + +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" +) + +// 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{} + DefaultMultipliers = Multipliers{} + DefaultUSDXClaims = USDXMintingClaims{} + DefaultHardClaims = HardLiquidityProviderClaims{} + DefaultGenesisAccumulationTimes = GenesisAccumulationTimes{} + DefaultClaimEnd = tmtime.Canonical(time.Unix(0, 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) GenesisState { + return GenesisState{ + Params: params, + USDXAccumulationTimes: usdxAccumTimes, + HardSupplyAccumulationTimes: hardSupplyAccumTimes, + HardBorrowAccumulationTimes: hardBorrowAccumTimes, + HardDelegatorAccumulationTimes: hardDelegatorAccumTimes, + USDXMintingClaims: c, + } +} + +// 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"` + RewardFactor sdk.Dec `json:"reward_factor" yaml:"reward_factor"` +} + +// NewGenesisAccumulationTime returns a new GenesisAccumulationTime +func NewGenesisAccumulationTime(ctype string, prevTime time.Time, factor sdk.Dec) GenesisAccumulationTime { + return GenesisAccumulationTime{ + CollateralType: ctype, + PreviousAccumulationTime: prevTime, + RewardFactor: factor, + } +} + +// 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 gat.RewardFactor.LT(sdk.ZeroDec()) { + return fmt.Errorf("reward factor should be ≥ 0.0, is %s for %s", gat.RewardFactor, gat.CollateralType) + } + 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 RewardPeriods `json:"hard_supply_reward_periods" yaml:"hard_supply_reward_periods"` + HardBorrowRewardPeriods RewardPeriods `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, hardSupply, hardBorrow, 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, DefaultRewardPeriods, + DefaultRewardPeriods, DefaultRewardPeriods, DefaultMultipliers, DefaultClaimEnd) +} + +// 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, validateRewardPeriodsParam), + params.NewParamSetPair(KeyHardBorrowRewardPeriods, &p.HardBorrowRewardPeriods, validateRewardPeriodsParam), + 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 := validateRewardPeriodsParam(p.HardSupplyRewardPeriods); err != nil { + return err + } + + if err := validateRewardPeriodsParam(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 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.IsZero() { + 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.IsZero() { + return errors.New("reward period start time cannot be 0") + } + if rp.End.IsZero() { + 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) +} + +// -------------- 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 { + BaseClaim `json:"base_claim" yaml:"base_claim"` + SupplyRewardIndexes RewardIndexes `json:"supply_reward_indexes" yaml:"supply_reward_indexes"` + BorrowRewardIndexes RewardIndexes `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, reward sdk.Coin, supplyRewardIndexes, + borrowRewardIndexes, delegatorRewardIndexes RewardIndexes) HardLiquidityProviderClaim { + return HardLiquidityProviderClaim{ + BaseClaim: BaseClaim{ + Owner: owner, + Reward: reward, + }, + 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.Coin { 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.BaseClaim.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.BaseClaim, 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 +} + +// -------------- Subcomponents of Custom Claim Types -------------- + +// TODO: refactor RewardPeriod name from 'collateralType' to 'denom' + +// 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 + +// Validate validation for reward indexes +func (ris RewardIndexes) Validate() error { + for _, ri := range ris { + if err := ri.Validate(); err != nil { + return err + } + } + return nil +} diff --git a/x/incentive/types/genesis.go b/x/incentive/types/genesis.go index ee813812..d508bc2d 100644 --- a/x/incentive/types/genesis.go +++ b/x/incentive/types/genesis.go @@ -10,26 +10,38 @@ import ( // GenesisState is the state that must be provided at genesis. type GenesisState struct { - Params Params `json:"params" yaml:"params"` - PreviousAccumulationTimes GenesisAccumulationTimes `json:"previous_accumulation_times" yaml:"previous_accumulation_times"` - USDXMintingClaims USDXMintingClaims `json:"usdx_minting_claims" yaml:"usdx_minting_claims"` + Params Params `json:"params" yaml:"params"` + USDXAccumulationTimes GenesisAccumulationTimes `json:"usdx_accumulation_times" yaml:"usdx_accumulation_times"` + HardSupplyAccumulationTimes GenesisAccumulationTimes `json:"hard_supply_accumulation_times" yaml:"hard_supply_accumulation_times"` + HardBorrowAccumulationTimes GenesisAccumulationTimes `json:"hard_borrow_accumulation_times" yaml:"hard_borrow_accumulation_times"` + 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, prevAccumTimes GenesisAccumulationTimes, c USDXMintingClaims) GenesisState { +func NewGenesisState(params Params, usdxAccumTimes, hardSupplyAccumTimes, hardBorrowAccumTimes, hardDelegatorAccumTimes GenesisAccumulationTimes, c USDXMintingClaims, hc HardLiquidityProviderClaims) GenesisState { return GenesisState{ - Params: params, - PreviousAccumulationTimes: prevAccumTimes, - USDXMintingClaims: c, + 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(), - PreviousAccumulationTimes: GenesisAccumulationTimes{}, - USDXMintingClaims: DefaultClaims, + Params: DefaultParams(), + USDXAccumulationTimes: GenesisAccumulationTimes{}, + HardSupplyAccumulationTimes: GenesisAccumulationTimes{}, + HardBorrowAccumulationTimes: GenesisAccumulationTimes{}, + HardDelegatorAccumulationTimes: GenesisAccumulationTimes{}, + USDXMintingClaims: DefaultUSDXClaims, + HardLiquidityProviderClaims: DefaultHardClaims, } } @@ -39,10 +51,22 @@ func (gs GenesisState) Validate() error { if err := gs.Params.Validate(); err != nil { return err } - if err := gs.PreviousAccumulationTimes.Validate(); err != nil { + 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() } diff --git a/x/incentive/types/genesis_test.go b/x/incentive/types/genesis_test.go index f149617a..bfcc921f 100644 --- a/x/incentive/types/genesis_test.go +++ b/x/incentive/types/genesis_test.go @@ -32,7 +32,7 @@ func TestGenesisStateValidate(t *testing.T) { args: args{ params: DefaultParams(), genAccTimes: DefaultGenesisAccumulationTimes, - claims: DefaultClaims, + claims: DefaultUSDXClaims, }, errArgs: errArgs{ expectPass: true, @@ -95,7 +95,7 @@ func TestGenesisStateValidate(t *testing.T) { RewardFactor: sdk.MustNewDecFromStr("-0.1"), }, }, - claims: DefaultClaims, + claims: DefaultUSDXClaims, }, errArgs: errArgs{ expectPass: false, @@ -131,7 +131,7 @@ func TestGenesisStateValidate(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - gs := NewGenesisState(tc.args.params, tc.args.genAccTimes, tc.args.claims) + gs := NewGenesisState(tc.args.params, tc.args.genAccTimes, tc.args.genAccTimes, tc.args.genAccTimes, tc.args.genAccTimes, tc.args.claims, DefaultHardClaims) err := gs.Validate() if tc.errArgs.expectPass { require.NoError(t, err, tc.name) diff --git a/x/incentive/types/params.go b/x/incentive/types/params.go index e63bf307..bd3ea977 100644 --- a/x/incentive/types/params.go +++ b/x/incentive/types/params.go @@ -34,7 +34,8 @@ var ( DefaultRewardPeriods = RewardPeriods{} DefaultMultiRewardPeriods = MultiRewardPeriods{} DefaultMultipliers = Multipliers{} - DefaultClaims = USDXMintingClaims{} + DefaultUSDXClaims = USDXMintingClaims{} + DefaultHardClaims = HardLiquidityProviderClaims{} DefaultGenesisAccumulationTimes = GenesisAccumulationTimes{} DefaultClaimEnd = tmtime.Canonical(time.Unix(1, 0)) GovDenom = cdptypes.DefaultGovDenom