diff --git a/app/test_common.go b/app/test_common.go index ccb5455a..c458f620 100644 --- a/app/test_common.go +++ b/app/test_common.go @@ -113,6 +113,8 @@ func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper { return tApp.fe func (tApp TestApp) GetLiquidKeeper() liquidkeeper.Keeper { return tApp.liquidKeeper } func (tApp TestApp) GetEarnKeeper() earnkeeper.Keeper { return tApp.earnKeeper } +func (tApp TestApp) GetStoreKey(s string) sdk.StoreKey { return tApp.keys[s] } + // LegacyAmino returns the app's amino codec. func (app *App) LegacyAmino() *codec.LegacyAmino { return app.legacyAmino diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 3e8d03ad..5d14b711 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4561,6 +4561,7 @@ MultipliersPerDenom is a map of denoms to a set of multipliers | ----- | ---- | ----- | ----------- | | `denom` | [string](#string) | | | | `multipliers` | [Multiplier](#kava.incentive.v1beta1.Multiplier) | repeated | | +| `module_name` | [string](#string) | | | diff --git a/proto/kava/incentive/v1beta1/params.proto b/proto/kava/incentive/v1beta1/params.proto index e35d0bc5..7f78c4af 100644 --- a/proto/kava/incentive/v1beta1/params.proto +++ b/proto/kava/incentive/v1beta1/params.proto @@ -50,6 +50,8 @@ message MultipliersPerDenom { string denom = 1; repeated Multiplier multipliers = 2 [(gogoproto.castrepeated) = "Multipliers", (gogoproto.nullable) = false]; + + string module_name = 3; } // Params diff --git a/x/incentive/genesis_test.go b/x/incentive/genesis_test.go index 887c8ea0..e7e8b9af 100644 --- a/x/incentive/genesis_test.go +++ b/x/incentive/genesis_test.go @@ -146,6 +146,13 @@ func (suite *GenesisTestSuite) TestExportedGenesisMatchesImported() { types.NewMultiplier("large", 12, d("1.0")), }, }, + { + Denom: "ukava", + Multipliers: types.Multipliers{ + types.NewMultiplier("large", 12, d("1.0")), + }, + ModuleName: "earn", + }, { Denom: "hard", Multipliers: types.Multipliers{ diff --git a/x/incentive/keeper/claim.go b/x/incentive/keeper/claim.go index ef75f93a..8ce7185c 100644 --- a/x/incentive/keeper/claim.go +++ b/x/incentive/keeper/claim.go @@ -5,6 +5,8 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/kava-labs/kava/x/incentive/types" + + earntypes "github.com/kava-labs/kava/x/earn/types" ) // ClaimUSDXMintingReward pays out funds from a claim to a receiver account. @@ -15,7 +17,7 @@ func (k Keeper) ClaimUSDXMintingReward(ctx sdk.Context, owner, receiver sdk.AccA return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", owner) } - multiplier, found := k.GetMultiplierByDenom(ctx, types.USDXMintingRewardDenom, multiplierName) + multiplier, found := k.GetMultiplierByDenom(ctx, types.USDXMintingRewardDenom, multiplierName, "") if !found { return sdkerrors.Wrapf(types.ErrInvalidMultiplier, "denom '%s' has no multiplier '%s'", types.USDXMintingRewardDenom, multiplierName) } @@ -59,7 +61,7 @@ func (k Keeper) ClaimUSDXMintingReward(ctx sdk.Context, owner, receiver sdk.AccA // ClaimHardReward pays out funds from a claim to a receiver account. // Rewards are removed from a claim and paid out according to the multiplier, which reduces the reward amount in exchange for shorter vesting times. func (k Keeper) ClaimHardReward(ctx sdk.Context, owner, receiver sdk.AccAddress, denom string, multiplierName string) error { - multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName) + multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName, "") if !found { return sdkerrors.Wrapf(types.ErrInvalidMultiplier, "denom '%s' has no multiplier '%s'", denom, multiplierName) } @@ -114,7 +116,7 @@ func (k Keeper) ClaimDelegatorReward(ctx sdk.Context, owner, receiver sdk.AccAdd return sdkerrors.Wrapf(types.ErrClaimNotFound, "address: %s", owner) } - multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName) + multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName, "") if !found { return sdkerrors.Wrapf(types.ErrInvalidMultiplier, "denom '%s' has no multiplier '%s'", denom, multiplierName) } @@ -163,7 +165,7 @@ func (k Keeper) ClaimDelegatorReward(ctx sdk.Context, owner, receiver sdk.AccAdd // ClaimSwapReward pays out funds from a claim to a receiver account. // Rewards are removed from a claim and paid out according to the multiplier, which reduces the reward amount in exchange for shorter vesting times. func (k Keeper) ClaimSwapReward(ctx sdk.Context, owner, receiver sdk.AccAddress, denom string, multiplierName string) error { - multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName) + multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName, "") if !found { return sdkerrors.Wrapf(types.ErrInvalidMultiplier, "denom '%s' has no multiplier '%s'", denom, multiplierName) } @@ -210,7 +212,7 @@ func (k Keeper) ClaimSwapReward(ctx sdk.Context, owner, receiver sdk.AccAddress, // ClaimSavingsReward is a stub method for MsgServer interface compliance func (k Keeper) ClaimSavingsReward(ctx sdk.Context, owner, receiver sdk.AccAddress, denom string, multiplierName string) error { - multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName) + multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName, "") if !found { return sdkerrors.Wrapf(types.ErrInvalidMultiplier, "denom '%s' has no multiplier '%s'", denom, multiplierName) } @@ -260,7 +262,7 @@ func (k Keeper) ClaimSavingsReward(ctx sdk.Context, owner, receiver sdk.AccAddre // ClaimEarnReward pays out funds from a claim to a receiver account. // Rewards are removed from a claim and paid out according to the multiplier, which reduces the reward amount in exchange for shorter vesting times. func (k Keeper) ClaimEarnReward(ctx sdk.Context, owner, receiver sdk.AccAddress, denom string, multiplierName string) error { - multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName) + multiplier, found := k.GetMultiplierByDenom(ctx, denom, multiplierName, earntypes.ModuleName) if !found { return sdkerrors.Wrapf(types.ErrInvalidMultiplier, "denom '%s' has no multiplier '%s'", denom, multiplierName) } diff --git a/x/incentive/keeper/claim_test.go b/x/incentive/keeper/claim_test.go index 4ca39a96..843a1dd1 100644 --- a/x/incentive/keeper/claim_test.go +++ b/x/incentive/keeper/claim_test.go @@ -7,7 +7,11 @@ import ( "github.com/stretchr/testify/suite" + earntypes "github.com/kava-labs/kava/x/earn/types" "github.com/kava-labs/kava/x/incentive/types" + + acctypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) // ClaimTests runs unit tests for the keeper Claim methods @@ -84,3 +88,97 @@ func (suite *ClaimTests) TestCannotClaimAfterEndTime() { err := suite.keeper.ClaimDelegatorReward(suite.ctx, claim.Owner, claim.Owner, "hard", "small") suite.ErrorIs(err, types.ErrClaimExpired) } + +func (suite *ClaimTests) TestClaimEarnNoLockup() { + vaultDenom1 := "bkava-meow" + vaultDenom2 := "bkava-woof" + + suite.ctx = NewTestContext( + suite.incentiveStoreKey, + suite.app.GetStoreKey(acctypes.StoreKey), + suite.app.GetStoreKey(banktypes.StoreKey), + ) + + err := suite.app.FundModuleAccount(suite.ctx, types.IncentiveMacc, cs(c("ukava", 100000000000))) + suite.NoError(err) + + accAddr := arbitraryAddress() + + ak := suite.app.GetAccountKeeper() + acc := ak.NewAccountWithAddress(suite.ctx, accAddr) + ak.SetAccount(suite.ctx, acc) + + bk := suite.app.GetBankKeeper() + + earnKeeper := newFakeEarnKeeper(). + addVault(vaultDenom1, earntypes.NewVaultShare(vaultDenom1, d("1000000"))). + addVault(vaultDenom2, earntypes.NewVaultShare(vaultDenom2, d("1000000"))) + + liquidKeeper := newFakeLiquidKeeper(). + addDerivative(vaultDenom1, i(1000000)). + addDerivative(vaultDenom2, i(1000000)) + + suite.keeper = suite.NewKeeper( + &fakeParamSubspace{}, + bk, + nil, nil, + ak, + nil, nil, nil, + liquidKeeper, earnKeeper, + ) + + suite.keeper.SetParams(suite.ctx, types.Params{ + ClaimMultipliers: types.MultipliersPerDenoms{ + { + Denom: "ukava", + Multipliers: types.Multipliers{ + types.NewMultiplier("large", 0, d("1")), + }, + ModuleName: earntypes.ModuleName, + }, + { + Denom: "ukava", + Multipliers: types.Multipliers{ + types.NewMultiplier("small", 1, d("0.2")), + }, + // No module name to apply to other non-earn modules + ModuleName: "", + }, + }, + ClaimEnd: distantFuture, + }) + + earnClaim := types.EarnClaim{ + BaseMultiClaim: types.BaseMultiClaim{ + Owner: accAddr, + Reward: cs(c("earn", 100), c("ukava", 100)), + }, + } + suite.storeEarnClaim(earnClaim) + + claim := types.DelegatorClaim{ + BaseMultiClaim: types.BaseMultiClaim{ + Owner: accAddr, + Reward: cs(c("earn", 100), c("ukava", 100)), + }, + } + suite.storeDelegatorClaim(claim) + + balBefore := bk.GetAllBalances(suite.ctx, accAddr) + suite.Equal(cs(), balBefore) + + // Claim for earn module + err = suite.keeper.ClaimEarnReward(suite.ctx, earnClaim.Owner, earnClaim.Owner, "ukava", "large") + suite.NoError(err) + + // Check balances + balAfter := bk.GetAllBalances(suite.ctx, accAddr) + suite.Equal(cs(c("ukava", 100)), balAfter) + + // Claim for non-earn module + err = suite.keeper.ClaimDelegatorReward(suite.ctx, claim.Owner, claim.Owner, "ukava", "small") + suite.NoError(err) + + balAfter2 := bk.GetAllBalances(suite.ctx, accAddr) + suite.Equal(cs(c("ukava", 120)), balAfter2, "claiming ukava for non-earn is multiplied by 0.2") +} diff --git a/x/incentive/keeper/params.go b/x/incentive/keeper/params.go index c98e4bd9..30149cdd 100644 --- a/x/incentive/keeper/params.go +++ b/x/incentive/keeper/params.go @@ -76,12 +76,26 @@ func (k Keeper) GetSavingsRewardPeriods(ctx sdk.Context, denom string) (types.Mu } // GetMultiplierByDenom fetches a multiplier from the params matching the denom and name. -func (k Keeper) GetMultiplierByDenom(ctx sdk.Context, denom string, name string) (types.Multiplier, bool) { +func (k Keeper) GetMultiplierByDenom( + ctx sdk.Context, + denom string, + multiplierName string, + moduleName string, +) (types.Multiplier, bool) { params := k.GetParams(ctx) + // Try specific exact module/CollateralType match first for _, dm := range params.ClaimMultipliers { - if dm.Denom == denom { - m, found := dm.Multipliers.Get(name) + if dm.Denom == denom && dm.ModuleName == moduleName { + m, found := dm.Multipliers.Get(multiplierName) + return m, found + } + } + + // Fallback to generic denom match + for _, dm := range params.ClaimMultipliers { + if dm.Denom == denom && dm.ModuleName == "" { + m, found := dm.Multipliers.Get(multiplierName) return m, found } } diff --git a/x/incentive/keeper/params_test.go b/x/incentive/keeper/params_test.go new file mode 100644 index 00000000..2e7c7b2e --- /dev/null +++ b/x/incentive/keeper/params_test.go @@ -0,0 +1,117 @@ +package keeper_test + +import ( + "testing" + + earntypes "github.com/kava-labs/kava/x/earn/types" + "github.com/kava-labs/kava/x/incentive/types" + "github.com/stretchr/testify/suite" +) + +type ParamsTests struct { + unitTester +} + +func TestParamsTests(t *testing.T) { + suite.Run(t, new(ParamsTests)) +} + +func (suite *ParamsTests) TestGetMultiplierByDenom() { + subspace := &fakeParamSubspace{ + params: types.Params{ + ClaimMultipliers: types.MultipliersPerDenoms{ + { + Denom: "hard", + Multipliers: types.Multipliers{ + types.NewMultiplier("small", 1, d("0.2")), + }, + }, + { + Denom: "ukava", + Multipliers: types.Multipliers{ + types.NewMultiplier("large", 0, d("1")), + }, + ModuleName: earntypes.ModuleName, + }, + { + Denom: "ukava", + Multipliers: types.Multipliers{ + types.NewMultiplier("large", 1, d("0.2")), + }, + ModuleName: "", + }, + }, + }, + } + suite.keeper = suite.NewKeeper(subspace, nil, nil, nil, nil, nil, nil, nil, nil, nil) + + tests := []struct { + name string + denom string + moduleName string + multiplier string + expected types.Multiplier + }{ + { + name: "hard claim", + denom: "hard", + moduleName: "", + multiplier: "small", + expected: types.NewMultiplier("small", 1, d("0.2")), + }, + { + name: "ukava earn", + denom: "ukava", + moduleName: earntypes.ModuleName, + multiplier: "large", + expected: types.NewMultiplier("large", 0, d("1.0")), + }, + { + name: "ukava non-earn", + denom: "ukava", + moduleName: "", + multiplier: "large", + expected: types.NewMultiplier("large", 1, d("0.2")), + }, + } + + for _, tc := range tests { + suite.Run(tc.name, func() { + multiplier, found := suite.keeper.GetMultiplierByDenom( + suite.ctx, + tc.denom, + tc.multiplier, + tc.moduleName, + ) + suite.Require().True(found) + suite.Require().Equal(tc.expected, multiplier) + }) + } +} + +func (suite *ParamsTests) TestEmptyModuleNameByDefault() { + subspace := &fakeParamSubspace{ + params: types.Params{ + ClaimMultipliers: types.MultipliersPerDenoms{ + { + Denom: "hard", + Multipliers: types.Multipliers{ + types.NewMultiplier("small", 1, d("0.2")), + }, + }, + { + Denom: "ukava", + Multipliers: types.Multipliers{ + types.NewMultiplier("large", 0, d("1")), + }, + }, + }, + }, + } + suite.keeper = suite.NewKeeper(subspace, nil, nil, nil, nil, nil, nil, nil, nil, nil) + + params := suite.keeper.GetParams(suite.ctx) + for _, m := range params.ClaimMultipliers { + suite.Require().Equal("", m.ModuleName) + } +} diff --git a/x/incentive/keeper/unit_test.go b/x/incentive/keeper/unit_test.go index 48ed96eb..7ec6a199 100644 --- a/x/incentive/keeper/unit_test.go +++ b/x/incentive/keeper/unit_test.go @@ -45,6 +45,7 @@ func NewTestContext(requiredStoreKeys ...sdk.StoreKey) sdk.Context { type unitTester struct { suite.Suite keeper keeper.Keeper + app app.TestApp ctx sdk.Context cdc codec.Codec @@ -52,8 +53,8 @@ type unitTester struct { } func (suite *unitTester) SetupSuite() { - tApp := app.NewTestApp() - suite.cdc = tApp.AppCodec() + suite.app = app.NewTestApp() + suite.cdc = suite.app.AppCodec() suite.incentiveStoreKey = sdk.NewKVStoreKey(types.StoreKey) } @@ -74,7 +75,12 @@ func (suite *unitTester) NewKeeper( ak types.AccountKeeper, stk types.StakingKeeper, swk types.SwapKeeper, svk types.SavingsKeeper, lqk types.LiquidKeeper, ek types.EarnKeeper, ) keeper.Keeper { - return keeper.NewKeeper(suite.cdc, suite.incentiveStoreKey, paramSubspace, bk, cdpk, hk, ak, stk, swk, svk, lqk, ek) + return keeper.NewKeeper( + suite.cdc, + suite.incentiveStoreKey, + paramSubspace, + bk, cdpk, hk, ak, stk, swk, svk, lqk, ek, + ) } func (suite *unitTester) storeGlobalBorrowIndexes(indexes types.MultiRewardIndexes) { diff --git a/x/incentive/types/multipliers.go b/x/incentive/types/multipliers.go index ba0bc042..94094632 100644 --- a/x/incentive/types/multipliers.go +++ b/x/incentive/types/multipliers.go @@ -70,10 +70,12 @@ func (mpd MultipliersPerDenoms) Validate() error { return err } - if foundDenoms[item.Denom] { - return fmt.Errorf("") + // Allow multiple multipliers per denom with different module names + // Effectively a composite key (Denom, ModuleName) + if foundDenoms[item.Denom+item.ModuleName] { + return fmt.Errorf("duplicate denom+moduleName %s", item.Denom+item.ModuleName) } - foundDenoms[item.Denom] = true + foundDenoms[item.Denom+item.ModuleName] = true } return nil } diff --git a/x/incentive/types/params.pb.go b/x/incentive/types/params.pb.go index 69582b02..56a331ce 100644 --- a/x/incentive/types/params.pb.go +++ b/x/incentive/types/params.pb.go @@ -157,6 +157,7 @@ var xxx_messageInfo_Multiplier proto.InternalMessageInfo type MultipliersPerDenom struct { Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` Multipliers Multipliers `protobuf:"bytes,2,rep,name=multipliers,proto3,castrepeated=Multipliers" json:"multipliers"` + ModuleName string `protobuf:"bytes,3,opt,name=module_name,json=moduleName,proto3" json:"module_name,omitempty"` } func (m *MultipliersPerDenom) Reset() { *m = MultipliersPerDenom{} } @@ -251,56 +252,57 @@ func init() { } var fileDescriptor_bb8833f5d745eac9 = []byte{ - // 774 bytes of a gzipped FileDescriptorProto + // 792 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x96, 0xcf, 0x6e, 0xd3, 0x4a, - 0x14, 0xc6, 0xe3, 0xfc, 0xbb, 0xc9, 0xb4, 0xbd, 0xb7, 0x9d, 0x46, 0xb9, 0xbe, 0xb9, 0xc8, 0xa9, - 0x52, 0x04, 0x41, 0x55, 0x6d, 0x0a, 0x12, 0x0b, 0x76, 0x98, 0x82, 0x84, 0x44, 0xa5, 0xca, 0x2d, - 0x12, 0xb0, 0x89, 0x26, 0xf6, 0xd4, 0xb5, 0x6a, 0x7b, 0xac, 0x99, 0x49, 0xda, 0x88, 0x05, 0x12, - 0x0b, 0x76, 0x48, 0x15, 0x0b, 0x1e, 0xa2, 0xaf, 0xc1, 0xa6, 0xcb, 0x8a, 0x15, 0x62, 0xd1, 0x42, - 0xfa, 0x22, 0x68, 0xc6, 0x6e, 0xe3, 0xa4, 0x69, 0xa1, 0x52, 0x36, 0xac, 0x32, 0x3e, 0x73, 0xce, - 0xf9, 0x7d, 0xfe, 0xc6, 0x67, 0x14, 0xb0, 0xb8, 0x83, 0xba, 0xc8, 0xf0, 0x42, 0x1b, 0x87, 0xdc, - 0xeb, 0x62, 0xa3, 0xbb, 0xd2, 0xc6, 0x1c, 0xad, 0x18, 0x11, 0xa2, 0x28, 0x60, 0x7a, 0x44, 0x09, - 0x27, 0xb0, 0x2a, 0x92, 0xf4, 0xf3, 0x24, 0x3d, 0x49, 0xaa, 0x55, 0x5c, 0xe2, 0x12, 0x99, 0x62, - 0x88, 0x55, 0x9c, 0x5d, 0xab, 0xbb, 0x84, 0xb8, 0x3e, 0x36, 0xe4, 0x53, 0xbb, 0xb3, 0x65, 0x70, - 0x2f, 0xc0, 0x8c, 0xa3, 0x20, 0x4a, 0x12, 0x34, 0x9b, 0xb0, 0x80, 0x30, 0xa3, 0x8d, 0xd8, 0x00, - 0x68, 0x13, 0x2f, 0x8c, 0xf7, 0x1b, 0x1f, 0xb3, 0x60, 0xda, 0xc2, 0xbb, 0x88, 0x3a, 0xeb, 0x98, - 0x7a, 0xc4, 0x81, 0x55, 0x50, 0x44, 0xb6, 0x20, 0xab, 0xca, 0x82, 0xd2, 0x2c, 0x59, 0xc9, 0x13, - 0xbc, 0x0d, 0xfe, 0xb1, 0x89, 0xef, 0x23, 0x8e, 0x29, 0xf2, 0x5b, 0xbc, 0x17, 0x61, 0x35, 0xbb, - 0xa0, 0x34, 0xcb, 0xd6, 0xdf, 0x83, 0xf0, 0x66, 0x2f, 0xc2, 0xf0, 0x21, 0x28, 0x30, 0x8e, 0x28, - 0x57, 0x73, 0x0b, 0x4a, 0x73, 0xea, 0x5e, 0x4d, 0x8f, 0x25, 0xea, 0x67, 0x12, 0xf5, 0xcd, 0x33, - 0x89, 0x66, 0xe9, 0xf0, 0xb8, 0x9e, 0xd9, 0x3f, 0xa9, 0x2b, 0x56, 0x5c, 0x02, 0x1f, 0x80, 0x1c, - 0x0e, 0x1d, 0x35, 0x7f, 0x8d, 0x4a, 0x51, 0x00, 0xd7, 0x00, 0xa4, 0xf2, 0x25, 0x58, 0x2b, 0xc2, - 0xb4, 0xc5, 0xb0, 0x4d, 0x42, 0x47, 0x2d, 0xc8, 0x36, 0xff, 0xe9, 0xb1, 0x05, 0xba, 0xb0, 0xe0, - 0xcc, 0x4e, 0xfd, 0x31, 0xf1, 0x42, 0x33, 0x2f, 0xba, 0x58, 0xb3, 0x49, 0xe9, 0x3a, 0xa6, 0x1b, - 0xb2, 0xb0, 0xf1, 0x39, 0x0b, 0xe6, 0xd6, 0x3a, 0x3e, 0xf7, 0xfe, 0x7c, 0x67, 0x7a, 0x97, 0x38, - 0x93, 0xbb, 0xda, 0x99, 0xbb, 0xa2, 0xcb, 0xc1, 0x49, 0xbd, 0xe9, 0x7a, 0x7c, 0xbb, 0xd3, 0xd6, - 0x6d, 0x12, 0x18, 0xc9, 0x97, 0x14, 0xff, 0x2c, 0x33, 0x67, 0xc7, 0x10, 0xef, 0xca, 0x64, 0x01, - 0x1b, 0xe3, 0xe2, 0x07, 0x05, 0x00, 0xe9, 0x62, 0xe4, 0x7b, 0x98, 0x42, 0x08, 0xf2, 0x21, 0x0a, - 0x62, 0xf3, 0xca, 0x96, 0x5c, 0xc3, 0x45, 0x30, 0x13, 0x90, 0x90, 0x6f, 0xb3, 0x96, 0x4f, 0xec, - 0x9d, 0x4e, 0x24, 0x8d, 0xcb, 0x59, 0xd3, 0x71, 0xf0, 0xb9, 0x8c, 0xc1, 0xa7, 0xa0, 0xb8, 0x85, - 0x6c, 0x4e, 0xa8, 0xf4, 0x6d, 0xda, 0xd4, 0x85, 0xb6, 0x6f, 0xc7, 0xf5, 0x5b, 0xbf, 0xa1, 0x6d, - 0x15, 0xdb, 0x56, 0x52, 0xdd, 0x78, 0xaf, 0x80, 0xf9, 0x81, 0x1e, 0x21, 0x74, 0x15, 0x87, 0x24, - 0x80, 0x15, 0x50, 0x70, 0xc4, 0x22, 0x51, 0x16, 0x3f, 0xc0, 0x57, 0x60, 0x2a, 0x18, 0x24, 0xab, - 0x59, 0xe9, 0x58, 0x43, 0x1f, 0x3f, 0x9d, 0xfa, 0xa0, 0xaf, 0x39, 0x9f, 0x58, 0x37, 0x95, 0x62, - 0x59, 0xe9, 0x5e, 0x8d, 0x2f, 0x25, 0x50, 0x5c, 0x97, 0x33, 0x0f, 0x3f, 0x29, 0xe0, 0xff, 0x0e, - 0x73, 0xf6, 0x5a, 0x81, 0x17, 0x72, 0x2f, 0x74, 0x5b, 0xb1, 0x8b, 0xe2, 0xac, 0x3c, 0xe2, 0x30, - 0x55, 0x91, 0xd8, 0x9b, 0x97, 0x61, 0xd3, 0xdf, 0xa7, 0xb9, 0x22, 0xc0, 0xfd, 0xe3, 0xba, 0xfa, - 0x62, 0x63, 0xf5, 0xe5, 0x5a, 0xdc, 0x2f, 0x9d, 0xc0, 0x0e, 0x4e, 0xea, 0x33, 0x43, 0x01, 0x4b, - 0x15, 0xec, 0x71, 0xa9, 0xf0, 0x9d, 0x02, 0x6a, 0xdb, 0x42, 0x09, 0xeb, 0x44, 0x91, 0xdf, 0x1b, - 0xd5, 0x15, 0xdb, 0x71, 0xe7, 0x4a, 0x3b, 0x86, 0xc4, 0xd5, 0x12, 0x57, 0xe0, 0x85, 0x2d, 0x66, - 0xfd, 0x2b, 0x40, 0x1b, 0x92, 0x73, 0x89, 0x88, 0x36, 0xa1, 0x94, 0xec, 0x8e, 0x8a, 0xc8, 0x4d, - 0x5c, 0x84, 0x29, 0x39, 0xc3, 0x22, 0xde, 0x02, 0xd5, 0xc1, 0x3e, 0x76, 0x11, 0x27, 0x74, 0x54, - 0x41, 0x7e, 0x92, 0x0a, 0xaa, 0xe7, 0x98, 0x61, 0x01, 0x1d, 0x30, 0xcf, 0x76, 0x51, 0x34, 0xca, - 0x2e, 0x4c, 0x92, 0x3d, 0x27, 0x08, 0xc3, 0xd8, 0x2e, 0x98, 0xb3, 0x7d, 0xe4, 0x05, 0xad, 0xf4, - 0x18, 0x14, 0x25, 0x74, 0xe9, 0xd7, 0x63, 0x70, 0x3e, 0x5e, 0xe6, 0x8d, 0x04, 0x5b, 0x19, 0xb3, - 0xc9, 0xac, 0x59, 0xc9, 0x48, 0x6d, 0xc1, 0x47, 0xa0, 0x1c, 0x73, 0xc5, 0x7d, 0xf7, 0xd7, 0x35, - 0xee, 0xbb, 0x92, 0x2c, 0x7b, 0x12, 0x3a, 0xf0, 0x0d, 0xa8, 0x32, 0xd4, 0xf5, 0x42, 0x97, 0x8d, - 0x9a, 0x56, 0x9a, 0xa4, 0x69, 0x95, 0x04, 0x72, 0xe1, 0xb8, 0x30, 0xa2, 0xe1, 0x28, 0xb9, 0x3c, - 0xd1, 0xe3, 0x12, 0x84, 0xa1, 0x90, 0xf9, 0xec, 0xf0, 0x87, 0x96, 0x39, 0xec, 0x6b, 0xca, 0x51, - 0x5f, 0x53, 0xbe, 0xf7, 0x35, 0x65, 0xff, 0x54, 0xcb, 0x1c, 0x9d, 0x6a, 0x99, 0xaf, 0xa7, 0x5a, - 0xe6, 0xf5, 0x52, 0xea, 0xae, 0x14, 0x0a, 0x96, 0x7d, 0xd4, 0x66, 0x72, 0x65, 0xec, 0xa5, 0xfe, - 0x91, 0xc8, 0x4b, 0xb3, 0x5d, 0x94, 0x36, 0xdf, 0xff, 0x19, 0x00, 0x00, 0xff, 0xff, 0x18, 0x89, - 0x03, 0xa4, 0xb0, 0x08, 0x00, 0x00, + 0x14, 0xc6, 0xe3, 0xfc, 0xbb, 0xc9, 0xa4, 0xbd, 0xb7, 0x9d, 0x46, 0xb9, 0x26, 0x20, 0xbb, 0x4a, + 0x11, 0x04, 0x55, 0xb5, 0x29, 0x48, 0x2c, 0xd8, 0x61, 0x0a, 0x12, 0x12, 0x45, 0x95, 0x5b, 0x24, + 0x60, 0x63, 0x4d, 0xec, 0xa9, 0x6b, 0xd5, 0xf6, 0x58, 0x1e, 0x3b, 0x6d, 0xc4, 0x02, 0x89, 0x3d, + 0x52, 0xc5, 0x82, 0x57, 0x40, 0xea, 0x6b, 0xb0, 0xe9, 0xb2, 0x62, 0x85, 0x58, 0xb4, 0x90, 0xbe, + 0x08, 0x9a, 0xb1, 0xdb, 0x38, 0x69, 0x5a, 0xa8, 0x94, 0x0d, 0xab, 0x8c, 0xcf, 0x9c, 0x73, 0xbe, + 0x9f, 0xbf, 0xf1, 0x1c, 0x05, 0x2c, 0x6c, 0xa3, 0x2e, 0x52, 0x1d, 0xdf, 0xc4, 0x7e, 0xe4, 0x74, + 0xb1, 0xda, 0x5d, 0xee, 0xe0, 0x08, 0x2d, 0xab, 0x01, 0x0a, 0x91, 0x47, 0x95, 0x20, 0x24, 0x11, + 0x81, 0x0d, 0x96, 0xa4, 0x9c, 0x25, 0x29, 0x69, 0x52, 0xb3, 0x6e, 0x13, 0x9b, 0xf0, 0x14, 0x95, + 0xad, 0x92, 0xec, 0xa6, 0x6c, 0x13, 0x62, 0xbb, 0x58, 0xe5, 0x4f, 0x9d, 0x78, 0x53, 0x8d, 0x1c, + 0x0f, 0xd3, 0x08, 0x79, 0x41, 0x9a, 0x20, 0x99, 0x84, 0x7a, 0x84, 0xaa, 0x1d, 0x44, 0x07, 0x82, + 0x26, 0x71, 0xfc, 0x64, 0xbf, 0xf5, 0x31, 0x0f, 0xa6, 0x74, 0xbc, 0x83, 0x42, 0x6b, 0x0d, 0x87, + 0x0e, 0xb1, 0x60, 0x03, 0x94, 0x91, 0xc9, 0x94, 0x45, 0x61, 0x5e, 0x68, 0x57, 0xf4, 0xf4, 0x09, + 0xde, 0x06, 0xff, 0x99, 0xc4, 0x75, 0x51, 0x84, 0x43, 0xe4, 0x1a, 0x51, 0x2f, 0xc0, 0x62, 0x7e, + 0x5e, 0x68, 0x57, 0xf5, 0x7f, 0x07, 0xe1, 0x8d, 0x5e, 0x80, 0xe1, 0x43, 0x50, 0xa2, 0x11, 0x0a, + 0x23, 0xb1, 0x30, 0x2f, 0xb4, 0x6b, 0xf7, 0x9a, 0x4a, 0x82, 0xa8, 0x9c, 0x22, 0x2a, 0x1b, 0xa7, + 0x88, 0x5a, 0xe5, 0xe0, 0x48, 0xce, 0xed, 0x1d, 0xcb, 0x82, 0x9e, 0x94, 0xc0, 0x07, 0xa0, 0x80, + 0x7d, 0x4b, 0x2c, 0x5e, 0xa1, 0x92, 0x15, 0xc0, 0x55, 0x00, 0x43, 0xfe, 0x12, 0xd4, 0x08, 0x70, + 0x68, 0x50, 0x6c, 0x12, 0xdf, 0x12, 0x4b, 0xbc, 0xcd, 0x35, 0x25, 0xb1, 0x40, 0x61, 0x16, 0x9c, + 0xda, 0xa9, 0x3c, 0x26, 0x8e, 0xaf, 0x15, 0x59, 0x17, 0x7d, 0x26, 0x2d, 0x5d, 0xc3, 0xe1, 0x3a, + 0x2f, 0x6c, 0x7d, 0xc9, 0x83, 0xd9, 0xd5, 0xd8, 0x8d, 0x9c, 0xbf, 0xdf, 0x99, 0xde, 0x05, 0xce, + 0x14, 0x2e, 0x77, 0xe6, 0x2e, 0xeb, 0xb2, 0x7f, 0x2c, 0xb7, 0x6d, 0x27, 0xda, 0x8a, 0x3b, 0x8a, + 0x49, 0x3c, 0x35, 0xfd, 0x92, 0x92, 0x9f, 0x25, 0x6a, 0x6d, 0xab, 0xec, 0x5d, 0x29, 0x2f, 0xa0, + 0x63, 0x5c, 0xfc, 0x20, 0x00, 0xc0, 0x5d, 0x0c, 0x5c, 0x07, 0x87, 0x10, 0x82, 0xa2, 0x8f, 0xbc, + 0xc4, 0xbc, 0xaa, 0xce, 0xd7, 0x70, 0x01, 0x4c, 0x7b, 0xc4, 0x8f, 0xb6, 0xa8, 0xe1, 0x12, 0x73, + 0x3b, 0x0e, 0xb8, 0x71, 0x05, 0x7d, 0x2a, 0x09, 0x3e, 0xe7, 0x31, 0xf8, 0x14, 0x94, 0x37, 0x91, + 0x19, 0x91, 0x90, 0xfb, 0x36, 0xa5, 0x29, 0x8c, 0xed, 0xfb, 0x91, 0x7c, 0xeb, 0x0f, 0xd8, 0x56, + 0xb0, 0xa9, 0xa7, 0xd5, 0xad, 0xcf, 0x02, 0x98, 0x1b, 0xf0, 0x30, 0xd0, 0x15, 0xec, 0x13, 0x0f, + 0xd6, 0x41, 0xc9, 0x62, 0x8b, 0x94, 0x2c, 0x79, 0x80, 0xaf, 0x41, 0xcd, 0x1b, 0x24, 0x8b, 0x79, + 0xee, 0x58, 0x4b, 0x19, 0x7f, 0x3b, 0x95, 0x41, 0x5f, 0x6d, 0x2e, 0xb5, 0xae, 0x96, 0xd1, 0xd2, + 0xb3, 0xbd, 0xa0, 0x0c, 0x6a, 0x1e, 0xb1, 0x62, 0x17, 0x1b, 0xdc, 0x90, 0x02, 0x97, 0x05, 0x49, + 0xe8, 0x05, 0xf2, 0x70, 0xeb, 0x6b, 0x05, 0x94, 0xd7, 0xf8, 0x50, 0x80, 0x9f, 0x04, 0x70, 0x3d, + 0xa6, 0xd6, 0xae, 0xe1, 0x39, 0x7e, 0xe4, 0xf8, 0xb6, 0x91, 0xd8, 0xcc, 0x0e, 0xd3, 0x21, 0x16, + 0x15, 0x05, 0xce, 0x75, 0xf3, 0x22, 0xae, 0xec, 0x07, 0xac, 0x2d, 0x33, 0xb2, 0xfe, 0x91, 0x2c, + 0xbe, 0x5c, 0x5f, 0x79, 0xb5, 0x9a, 0xf4, 0xcb, 0x26, 0xd0, 0xfd, 0x63, 0x79, 0x7a, 0x28, 0xa0, + 0x8b, 0x4c, 0x7b, 0x5c, 0x2a, 0x7c, 0x2f, 0x80, 0xe6, 0x16, 0x23, 0xa1, 0x71, 0x10, 0xb8, 0xbd, + 0x51, 0xae, 0xc4, 0xaf, 0x3b, 0x97, 0xfa, 0x35, 0x04, 0xd7, 0x4c, 0x6d, 0x83, 0xe7, 0xb6, 0xa8, + 0xfe, 0x3f, 0x13, 0x5a, 0xe7, 0x3a, 0x17, 0x40, 0x74, 0x48, 0x18, 0x92, 0x9d, 0x51, 0x88, 0xc2, + 0xc4, 0x21, 0x34, 0xae, 0x33, 0x0c, 0xf1, 0x0e, 0x88, 0x16, 0x76, 0xb1, 0x8d, 0x22, 0x12, 0x8e, + 0x12, 0x14, 0x27, 0x49, 0xd0, 0x38, 0x93, 0x19, 0x06, 0x88, 0xc1, 0x1c, 0xdd, 0x41, 0xc1, 0xa8, + 0x76, 0x69, 0x92, 0xda, 0xb3, 0x4c, 0x61, 0x58, 0xb6, 0x0b, 0x66, 0x4d, 0x17, 0x39, 0x9e, 0x91, + 0xbd, 0x27, 0x65, 0x2e, 0xba, 0xf8, 0xfb, 0x7b, 0x72, 0x76, 0xff, 0xb4, 0x1b, 0xa9, 0x6c, 0x7d, + 0xcc, 0x26, 0xd5, 0x67, 0xb8, 0x46, 0x66, 0x0b, 0x3e, 0x02, 0xd5, 0x44, 0x97, 0x0d, 0xc4, 0x7f, + 0xae, 0x30, 0x10, 0x2b, 0xbc, 0xec, 0x89, 0x6f, 0xc1, 0xb7, 0xa0, 0x41, 0x51, 0xd7, 0xf1, 0x6d, + 0x3a, 0x6a, 0x5a, 0x65, 0x92, 0xa6, 0xd5, 0x53, 0x91, 0x73, 0xc7, 0x85, 0x51, 0xe8, 0x8f, 0x2a, + 0x57, 0x27, 0x7a, 0x5c, 0x4c, 0x61, 0x28, 0xa4, 0x3d, 0x3b, 0xf8, 0x29, 0xe5, 0x0e, 0xfa, 0x92, + 0x70, 0xd8, 0x97, 0x84, 0x1f, 0x7d, 0x49, 0xd8, 0x3b, 0x91, 0x72, 0x87, 0x27, 0x52, 0xee, 0xdb, + 0x89, 0x94, 0x7b, 0xb3, 0x98, 0x19, 0xa6, 0x8c, 0x60, 0xc9, 0x45, 0x1d, 0xca, 0x57, 0xea, 0x6e, + 0xe6, 0x2f, 0x0b, 0x9f, 0xaa, 0x9d, 0x32, 0xb7, 0xf9, 0xfe, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x87, 0x7b, 0x24, 0x65, 0xd1, 0x08, 0x00, 0x00, } func (m *RewardPeriod) Marshal() (dAtA []byte, err error) { @@ -504,6 +506,13 @@ func (m *MultipliersPerDenom) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ModuleName) > 0 { + i -= len(m.ModuleName) + copy(dAtA[i:], m.ModuleName) + i = encodeVarintParams(dAtA, i, uint64(len(m.ModuleName))) + i-- + dAtA[i] = 0x1a + } if len(m.Multipliers) > 0 { for iNdEx := len(m.Multipliers) - 1; iNdEx >= 0; iNdEx-- { { @@ -764,6 +773,10 @@ func (m *MultipliersPerDenom) Size() (n int) { n += 1 + l + sovParams(uint64(l)) } } + l = len(m.ModuleName) + if l > 0 { + n += 1 + l + sovParams(uint64(l)) + } return n } @@ -1464,6 +1477,38 @@ func (m *MultipliersPerDenom) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ModuleName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ModuleName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/incentive/types/params_test.go b/x/incentive/types/params_test.go index 187a4c47..201ff884 100644 --- a/x/incentive/types/params_test.go +++ b/x/incentive/types/params_test.go @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/suite" "github.com/kava-labs/kava/x/incentive/types" + + earntypes "github.com/kava-labs/kava/x/earn/types" ) type ParamTestSuite struct { @@ -100,6 +102,14 @@ func (suite *ParamTestSuite) TestParamValidation() { types.NewMultiplier("small", 1, sdk.MustNewDecFromStr("0.2")), types.NewMultiplier("large", 12, sdk.MustNewDecFromStr("1.0")), }, + ModuleName: "", + }, + { + Denom: "ukava", + Multipliers: types.Multipliers{ + types.NewMultiplier("large", 0, sdk.MustNewDecFromStr("1.0")), + }, + ModuleName: earntypes.ModuleName, }, }, ClaimEnd: time.Date(2025, 10, 15, 14, 0, 0, 0, time.UTC),