Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Add Proposal for multistaking module #131

Merged
merged 20 commits into from
Feb 28, 2024
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -7,9 +7,9 @@ DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bu
### Protobuf ###
###############################################################################

protoVer=0.14.0
protoImageName=ghcr.io/cosmos/proto-builder:$(protoVer)
protoImage=$(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)
protoVer=v0.7
protoImageName=tendermintdev/sdk-proto-gen:$(protoVer)
protoImage=$(DOCKER) run --network host --rm -v $(CURDIR):/workspace --workdir /workspace $(protoImageName)

proto-all: proto-format proto-lint proto-gen

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ require (
github.com/cosmos/cosmos-proto v1.0.0-alpha8
github.com/cosmos/cosmos-sdk v0.46.12
github.com/cosmos/gogoproto v1.4.11
github.com/gogo/protobuf v1.3.3
github.com/golang/protobuf v1.5.3
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
@@ -71,7 +72,6 @@ require (
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/gogo/gateway v1.1.0 // indirect
github.com/gogo/protobuf v1.3.3 // indirect
github.com/golang/glog v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
5 changes: 4 additions & 1 deletion test/simapp/app.go
Original file line number Diff line number Diff line change
@@ -119,6 +119,8 @@ var (
distrclient.ProposalHandler,
upgradeclient.LegacyProposalHandler,
upgradeclient.LegacyCancelProposalHandler,
multistaking.AddMultiStakingProposalHandler,
multistaking.UpdateBondWeightProposalHandler,
},
),
groupmodule.AppModuleBasic{},
@@ -300,7 +302,8 @@ func NewSimApp(
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
AddRoute(multistakingtypes.RouterKey, multistaking.NewMultiStakingProposalHandler(&app.MultiStakingKeeper))

govConfig := govtypes.DefaultConfig()
/*
85 changes: 85 additions & 0 deletions x/multi-staking/client/cli/proposal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package cli

import (
"github.com/realio-tech/multi-staking-module/x/multi-staking/types"
"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
sdk "github.com/cosmos/cosmos-sdk/types"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
)

func NewCmdSubmitAddMultiStakingCoinProposal() *cobra.Command {
cmd := &cobra.Command{
Use: "add-multistaking-coin [title] [description] [denom] [bond_weight] [deposit]",
Args: cobra.ExactArgs(5),
Short: "Submit an add multistaking coin proposal",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

bondWeight, err := sdk.NewDecFromStr(args[3])
if err != nil {
return err
}
from := clientCtx.GetFromAddress()
content := types.NewAddMultiStakingCoinProposal(
args[0], args[1], args[2], bondWeight,
)

deposit, err := sdk.ParseCoinsNormalized(args[4])
if err != nil {
return err
}

msg, err := govv1beta1.NewMsgSubmitProposal(content, deposit, from)
if err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

return cmd
}

func NewCmdUpdateBondWeightProposal() *cobra.Command {
cmd := &cobra.Command{
Use: "update-bond-weight [title] [description] [denom] [bond_weight] [deposit]",
Args: cobra.ExactArgs(5),
Short: "Submit update bond weight for bond coin proposal",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

bondWeight, err := sdk.NewDecFromStr(args[3])
if err != nil {
return err
}
from := clientCtx.GetFromAddress()
content := types.NewUpdateBondWeightProposal(
args[0], args[1], args[2], bondWeight,
)

deposit, err := sdk.ParseCoinsNormalized(args[4])
if err != nil {
return err
}

msg, err := govv1beta1.NewMsgSubmitProposal(content, deposit, from)
if err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

return cmd
}
4 changes: 3 additions & 1 deletion x/multi-staking/keeper/keeper_test.go
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ import (

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
@@ -26,6 +27,7 @@ type KeeperTestSuite struct {
app *simapp.SimApp
ctx sdk.Context
msKeeper *multistakingkeeper.Keeper
govKeeper govkeeper.Keeper
msgServer stakingtypes.MsgServer
}

@@ -34,7 +36,7 @@ func (suite *KeeperTestSuite) SetupTest() {
ctx := app.BaseApp.NewContext(false, tmproto.Header{Height: app.LastBlockHeight() + 1})
multiStakingMsgServer := multistakingkeeper.NewMsgServerImpl(app.MultiStakingKeeper)

suite.app, suite.ctx, suite.msKeeper, suite.msgServer = app, ctx, &app.MultiStakingKeeper, multiStakingMsgServer
suite.app, suite.ctx, suite.msKeeper, suite.govKeeper, suite.msgServer = app, ctx, &app.MultiStakingKeeper, app.GovKeeper, multiStakingMsgServer
}

func TestKeeperTestSuite(t *testing.T) {
62 changes: 62 additions & 0 deletions x/multi-staking/keeper/proposal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package keeper

import (
"fmt"

"github.com/realio-tech/multi-staking-module/x/multi-staking/types"

sdk "github.com/cosmos/cosmos-sdk/types"
)

// AddMultiStakingCoinProposal handles the proposals to add a new bond token
func (k Keeper) AddMultiStakingCoinProposal(
ctx sdk.Context,
p *types.AddMultiStakingCoinProposal,
) error {
_, found := k.GetBondWeight(ctx, p.Denom)
if found {
return fmt.Errorf("Error MultiStakingCoin %s already exist", p.Denom) //nolint:stylecheck
}

bondWeight := *p.BondWeight
if bondWeight.LTE(sdk.ZeroDec()) {
return fmt.Errorf("Error MultiStakingCoin BondWeight %s invalid", bondWeight) //nolint:stylecheck
}

k.SetBondWeight(ctx, p.Denom, bondWeight)

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeAddMultiStakingCoin,
sdk.NewAttribute(types.AttributeKeyDenom, p.Denom),
sdk.NewAttribute(types.AttributeKeyBondWeight, p.BondWeight.String()),
),
)
return nil
}

func (k Keeper) BondWeightProposal(
ctx sdk.Context,
p *types.UpdateBondWeightProposal,
) error {
_, found := k.GetBondWeight(ctx, p.Denom)
if !found {
return fmt.Errorf("Error MultiStakingCoin %s not found", p.Denom) //nolint:stylecheck
}

bondWeight := *p.UpdatedBondWeight
if bondWeight.LTE(sdk.ZeroDec()) {
return fmt.Errorf("Error MultiStakingCoin BondWeight %s invalid", bondWeight) //nolint:stylecheck
}

k.SetBondWeight(ctx, p.Denom, bondWeight)

ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeAddMultiStakingCoin,
sdk.NewAttribute(types.AttributeKeyDenom, p.Denom),
sdk.NewAttribute(types.AttributeKeyBondWeight, p.UpdatedBondWeight.String()),
),
)
return nil
}
141 changes: 141 additions & 0 deletions x/multi-staking/keeper/proposal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package keeper_test

import (
"github.com/realio-tech/multi-staking-module/x/multi-staking/types"

sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1types "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
)

func (suite *KeeperTestSuite) TestAddMultiStakingCoinProposal() {
bondWeight := sdk.NewDec(1)

for _, tc := range []struct {
desc string
malleate func(p *types.AddMultiStakingCoinProposal)
proposal *types.AddMultiStakingCoinProposal
shouldErr bool
}{
{
desc: "Success",
malleate: func(p *types.AddMultiStakingCoinProposal) {
_, found := suite.msKeeper.GetBondWeight(suite.ctx, p.Denom)
suite.Require().False(found)
},
proposal: &types.AddMultiStakingCoinProposal{
Title: "Add multistaking coin",
Description: "Add new multistaking coin",
Denom: "stake1",
BondWeight: &bondWeight,
},
shouldErr: false,
},
{
desc: "Error multistaking coin already exists",
malleate: func(p *types.AddMultiStakingCoinProposal) {
suite.msKeeper.SetBondWeight(suite.ctx, p.Denom, *p.BondWeight)
},
proposal: &types.AddMultiStakingCoinProposal{
Title: "Add multistaking coin",
Description: "Add new multistaking coin",
Denom: "stake2",
BondWeight: &bondWeight,
},
shouldErr: true,
},
} {
tc := tc
suite.Run(tc.desc, func() {
suite.SetupTest()
tc.malleate(tc.proposal)

legacyProposal, err := govv1types.NewLegacyContent(tc.proposal, authtypes.NewModuleAddress(govtypes.ModuleName).String())
suite.Require().NoError(err)

if !tc.shouldErr {
// store proposal
_, err = suite.govKeeper.SubmitProposal(suite.ctx, []sdk.Msg{legacyProposal}, "")
suite.Require().NoError(err)

// execute proposal
handler := suite.govKeeper.LegacyRouter().GetRoute(tc.proposal.ProposalRoute())
err = handler(suite.ctx, tc.proposal)
suite.Require().NoError(err)

_, found := suite.msKeeper.GetBondWeight(suite.ctx, tc.proposal.Denom)
suite.Require().True(found)
} else {
// store proposal
_, err = suite.govKeeper.SubmitProposal(suite.ctx, []sdk.Msg{legacyProposal}, "")
suite.Require().Error(err)
}
})
}
}

func (suite *KeeperTestSuite) TestUpdateBondWeightProposal() {
bondWeight := sdk.NewDec(1)

for _, tc := range []struct {
desc string
malleate func(p *types.UpdateBondWeightProposal)
proposal *types.UpdateBondWeightProposal
shouldErr bool
}{
{
desc: "Success",
malleate: func(p *types.UpdateBondWeightProposal) {
oldBondWeight := sdk.NewDec(2)
suite.msKeeper.SetBondWeight(suite.ctx, p.Denom, oldBondWeight)
},
proposal: &types.UpdateBondWeightProposal{
Title: "Add multistaking coin",
Description: "Add new multistaking coin",
Denom: "stake1",
UpdatedBondWeight: &bondWeight,
},
shouldErr: false,
},
{
desc: "Error multistaking coin not exists",
malleate: func(p *types.UpdateBondWeightProposal) {},
proposal: &types.UpdateBondWeightProposal{
Title: "Add multistaking coin",
Description: "Add new multistaking coin",
Denom: "stake2",
UpdatedBondWeight: &bondWeight,
},
shouldErr: true,
},
} {
tc := tc
suite.Run(tc.desc, func() {
suite.SetupTest()
tc.malleate(tc.proposal)

legacyProposal, err := govv1types.NewLegacyContent(tc.proposal, authtypes.NewModuleAddress(govtypes.ModuleName).String())
suite.Require().NoError(err)

if !tc.shouldErr {
// store proposal
_, err = suite.govKeeper.SubmitProposal(suite.ctx, []sdk.Msg{legacyProposal}, "")
suite.Require().NoError(err)

// execute proposal
handler := suite.govKeeper.LegacyRouter().GetRoute(tc.proposal.ProposalRoute())
err = handler(suite.ctx, tc.proposal)
suite.Require().NoError(err)

weight, found := suite.msKeeper.GetBondWeight(suite.ctx, tc.proposal.Denom)
suite.Require().True(found)
suite.Require().True(weight.Equal(bondWeight))
} else {
// store proposal
_, err = suite.govKeeper.SubmitProposal(suite.ctx, []sdk.Msg{legacyProposal}, "")
suite.Require().Error(err)
}
})
}
}
2 changes: 2 additions & 0 deletions x/multi-staking/module.go
Original file line number Diff line number Diff line change
@@ -39,10 +39,12 @@ func (AppModuleBasic) Name() string {

// RegisterLegacyAminoCodec register module codec
func (am AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
multistakingtypes.RegisterLegacyAminoCodec(cdc)
}

// RegisterInterfaces registers the module interface
func (am AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) {
multistakingtypes.RegisterInterfaces(reg)
}

// DefaultGenesis returns multi-staking module default genesis state.
Loading