diff --git a/x/gov/keeper/common_test.go b/x/gov/keeper/common_test.go index 7d6632e2..ac89e703 100644 --- a/x/gov/keeper/common_test.go +++ b/x/gov/keeper/common_test.go @@ -46,12 +46,34 @@ func getTestProposal() []sdk.Msg { } } +type mocks struct { + acctKeeper *govtestutil.MockAccountKeeper + bankKeeper *govtestutil.MockBankKeeper + stakingKeeper *govtestutil.MockStakingKeeper +} + +func mockAccountKeeperExpectations(ctx sdk.Context, m mocks) { + m.acctKeeper.EXPECT().GetModuleAddress(types.ModuleName).Return(govAcct).AnyTimes() + m.acctKeeper.EXPECT().GetModuleAccount(gomock.Any(), types.ModuleName).Return(authtypes.NewEmptyModuleAccount(types.ModuleName)).AnyTimes() +} + +func mockDefaultExpectations(ctx sdk.Context, m mocks) { + mockAccountKeeperExpectations(ctx, m) + trackMockBalances(m.bankKeeper) + m.stakingKeeper.EXPECT().TokensFromConsensusPower(ctx, gomock.Any()).DoAndReturn(func(ctx sdk.Context, power int64) math.Int { + return sdk.TokensFromConsensusPower(power, math.NewIntFromUint64(1000000)) + }).AnyTimes() + + m.stakingKeeper.EXPECT().BondDenom(ctx).Return("stake").AnyTimes() + m.stakingKeeper.EXPECT().IterateBondedValidatorsByPower(gomock.Any(), gomock.Any()).AnyTimes() + m.stakingKeeper.EXPECT().IterateDelegations(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + m.stakingKeeper.EXPECT().TotalBondedTokens(gomock.Any()).Return(math.NewInt(10000000)).AnyTimes() +} + // setupGovKeeper creates a govKeeper as well as all its dependencies. -func setupGovKeeper(t *testing.T) ( +func setupGovKeeper(t *testing.T, expectations ...func(sdk.Context, mocks)) ( *keeper.Keeper, - *govtestutil.MockAccountKeeper, - *govtestutil.MockBankKeeper, - *govtestutil.MockStakingKeeper, + mocks, moduletestutil.TestEncodingConfig, sdk.Context, ) { @@ -69,23 +91,23 @@ func setupGovKeeper(t *testing.T) ( // gomock initializations ctrl := gomock.NewController(t) - acctKeeper := govtestutil.NewMockAccountKeeper(ctrl) - bankKeeper := govtestutil.NewMockBankKeeper(ctrl) - stakingKeeper := govtestutil.NewMockStakingKeeper(ctrl) - acctKeeper.EXPECT().GetModuleAddress(types.ModuleName).Return(govAcct).AnyTimes() - acctKeeper.EXPECT().GetModuleAccount(gomock.Any(), types.ModuleName).Return(authtypes.NewEmptyModuleAccount(types.ModuleName)).AnyTimes() - trackMockBalances(bankKeeper) - stakingKeeper.EXPECT().TokensFromConsensusPower(ctx, gomock.Any()).DoAndReturn(func(ctx sdk.Context, power int64) math.Int { - return sdk.TokensFromConsensusPower(power, math.NewIntFromUint64(1000000)) - }).AnyTimes() - stakingKeeper.EXPECT().BondDenom(ctx).Return("stake").AnyTimes() - stakingKeeper.EXPECT().IterateBondedValidatorsByPower(gomock.Any(), gomock.Any()).AnyTimes() - stakingKeeper.EXPECT().IterateDelegations(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() - stakingKeeper.EXPECT().TotalBondedTokens(gomock.Any()).Return(math.NewInt(10000000)).AnyTimes() + m := mocks{ + acctKeeper: govtestutil.NewMockAccountKeeper(ctrl), + bankKeeper: govtestutil.NewMockBankKeeper(ctrl), + stakingKeeper: govtestutil.NewMockStakingKeeper(ctrl), + } + if len(expectations) == 0 { + mockDefaultExpectations(ctx, m) + } else { + for _, exp := range expectations { + exp(ctx, m) + } + } // Gov keeper initializations - govKeeper := keeper.NewKeeper(encCfg.Codec, key, acctKeeper, bankKeeper, stakingKeeper, msr, types.DefaultConfig(), govAcct.String()) + govKeeper := keeper.NewKeeper(encCfg.Codec, key, m.acctKeeper, m.bankKeeper, m.stakingKeeper, msr, types.DefaultConfig(), govAcct.String()) govKeeper.SetProposalID(ctx, 1) + govRouter := v1beta1.NewRouter() // Also register legacy gov handlers to test them too. govRouter.AddRoute(types.RouterKey, v1beta1.ProposalHandler) govKeeper.SetLegacyRouter(govRouter) @@ -96,7 +118,7 @@ func setupGovKeeper(t *testing.T) ( v1.RegisterMsgServer(msr, keeper.NewMsgServerImpl(govKeeper)) banktypes.RegisterMsgServer(msr, nil) // Nil is fine here as long as we never execute the proposal's Msgs. - return govKeeper, acctKeeper, bankKeeper, stakingKeeper, encCfg, ctx + return govKeeper, m, encCfg, ctx } // trackMockBalances sets up expected calls on the Mock BankKeeper, and also diff --git a/x/gov/keeper/deposit_test.go b/x/gov/keeper/deposit_test.go index 204dc665..d37cb53b 100644 --- a/x/gov/keeper/deposit_test.go +++ b/x/gov/keeper/deposit_test.go @@ -16,7 +16,8 @@ const ( ) func TestDeposits(t *testing.T) { - govKeeper, _, bankKeeper, stakingKeeper, _, ctx := setupGovKeeper(t) + govKeeper, mocks, _, ctx := setupGovKeeper(t) + bankKeeper, stakingKeeper := mocks.bankKeeper, mocks.stakingKeeper trackMockBalances(bankKeeper) TestAddrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(10000000)) @@ -193,7 +194,7 @@ func TestValidateInitialDeposit(t *testing.T) { for name, tc := range testcases { t.Run(name, func(t *testing.T) { - govKeeper, _, _, _, _, ctx := setupGovKeeper(t) + govKeeper, _, _, ctx := setupGovKeeper(t) params := v1.DefaultParams() params.MinDeposit = tc.minDeposit diff --git a/x/gov/keeper/hooks_test.go b/x/gov/keeper/hooks_test.go index b7fe0541..69084ccc 100644 --- a/x/gov/keeper/hooks_test.go +++ b/x/gov/keeper/hooks_test.go @@ -48,7 +48,8 @@ func (h *MockGovHooksReceiver) AfterProposalVotingPeriodEnded(ctx sdk.Context, p func TestHooks(t *testing.T) { minDeposit := v1.DefaultParams().MinDeposit - govKeeper, _, bankKeeper, stakingKeeper, _, ctx := setupGovKeeper(t) + govKeeper, mocks, _, ctx := setupGovKeeper(t) + bankKeeper, stakingKeeper := mocks.bankKeeper, mocks.stakingKeeper addrs := simtestutil.AddTestAddrs(bankKeeper, stakingKeeper, ctx, 1, minDeposit[0].Amount) govHooksReceiver := MockGovHooksReceiver{} diff --git a/x/gov/keeper/keeper_test.go b/x/gov/keeper/keeper_test.go index e5663db1..0c0f2e7c 100644 --- a/x/gov/keeper/keeper_test.go +++ b/x/gov/keeper/keeper_test.go @@ -40,7 +40,8 @@ func (suite *KeeperTestSuite) SetupSuite() { } func (suite *KeeperTestSuite) reset() { - govKeeper, acctKeeper, bankKeeper, stakingKeeper, encCfg, ctx := setupGovKeeper(suite.T()) + govKeeper, mocks, encCfg, ctx := setupGovKeeper(suite.T()) + acctKeeper, bankKeeper, stakingKeeper := mocks.acctKeeper, mocks.bankKeeper, mocks.stakingKeeper // Populate the gov account with some coins, as the TestProposal we have // is a MsgSend from the gov account. @@ -72,7 +73,7 @@ func (suite *KeeperTestSuite) reset() { } func TestIncrementProposalNumber(t *testing.T) { - govKeeper, _, _, _, _, ctx := setupGovKeeper(t) + govKeeper, _, _, ctx := setupGovKeeper(t) tp := TestProposal _, err := govKeeper.SubmitProposal(ctx, tp, "", "test", "summary", sdk.AccAddress("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r")) @@ -92,7 +93,7 @@ func TestIncrementProposalNumber(t *testing.T) { } func TestProposalQueues(t *testing.T) { - govKeeper, _, _, _, _, ctx := setupGovKeeper(t) + govKeeper, _, _, ctx := setupGovKeeper(t) // create test proposals tp := TestProposal diff --git a/x/gov/keeper/tally.go b/x/gov/keeper/tally.go index dda2ec61..2d06d945 100644 --- a/x/gov/keeper/tally.go +++ b/x/gov/keeper/tally.go @@ -95,12 +95,13 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal v1.Proposal) (passes bool, // TODO: Upgrade the spec to cover all of these cases & remove pseudocode. // If there is no staked coins, the proposal fails - if keeper.sk.TotalBondedTokens(ctx).IsZero() { + totalBondedTokens := keeper.sk.TotalBondedTokens(ctx) + if totalBondedTokens.IsZero() { return false, false, tallyResults } // If there is not enough quorum of votes, the proposal fails - percentVoting := totalVotingPower.Quo(sdk.NewDecFromInt(keeper.sk.TotalBondedTokens(ctx))) + percentVoting := totalVotingPower.Quo(sdk.NewDecFromInt(totalBondedTokens)) quorum, _ := sdk.NewDecFromStr(params.Quorum) if percentVoting.LT(quorum) { return false, params.BurnVoteQuorum, tallyResults diff --git a/x/gov/keeper/tally_test.go b/x/gov/keeper/tally_test.go new file mode 100644 index 00000000..1af0c030 --- /dev/null +++ b/x/gov/keeper/tally_test.go @@ -0,0 +1,370 @@ +package keeper_test + +import ( + "context" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + sdkmath "cosmossdk.io/math" + + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/atomone-hub/atomone/x/gov/keeper" +) + +func TestTally(t *testing.T) { + type suite struct { + t *testing.T + proposal v1.Proposal + valAddrs []sdk.ValAddress + delAddrs []sdk.AccAddress + keeper *keeper.Keeper + ctx sdk.Context + mocks mocks + } + + var ( + // handy functions + setTotalBonded = func(s suite, n int64) { + s.mocks.stakingKeeper.EXPECT().TotalBondedTokens(gomock.Any()).Return(sdkmath.NewInt(n)) + } + delegatorVote = func(s suite, voter sdk.AccAddress, delegations []stakingtypes.Delegation, vote v1.VoteOption) { + err := s.keeper.AddVote(s.ctx, s.proposal.Id, voter, v1.NewNonSplitVoteOption(vote), "") + require.NoError(s.t, err) + s.mocks.stakingKeeper.EXPECT(). + IterateDelegations(s.ctx, voter, gomock.Any()). + DoAndReturn( + func(ctx context.Context, voter sdk.AccAddress, fn func(index int64, d stakingtypes.DelegationI) bool) error { + for i, d := range delegations { + fn(int64(i), d) + } + return nil + }) + } + validatorVote = func(s suite, voter sdk.ValAddress, vote v1.VoteOption) { + // validatorVote is like delegatorVote but without delegations + delegatorVote(s, sdk.AccAddress(voter), nil, vote) + } + ) + tests := []struct { + name string + setup func(suite) + expectedPass bool + expectedBurn bool + expectedTally v1.TallyResult + expectedError string + }{ + { + name: "no votes, no bonded tokens: prop fails", + setup: func(s suite) { + setTotalBonded(s, 0) + }, + expectedPass: false, + expectedBurn: false, + expectedTally: v1.TallyResult{ + YesCount: "0", + AbstainCount: "0", + NoCount: "0", + NoWithVetoCount: "0", + }, + }, + { + name: "no votes: prop fails/burn deposit", + setup: func(s suite) { + setTotalBonded(s, 10000000) + }, + expectedPass: false, + expectedBurn: true, // burn because quorum not reached + expectedTally: v1.TallyResult{ + YesCount: "0", + AbstainCount: "0", + NoCount: "0", + NoWithVetoCount: "0", + }, + }, + { + name: "one validator votes: prop fails/burn deposit", + setup: func(s suite) { + setTotalBonded(s, 10000000) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_NO) + }, + expectedPass: false, + expectedBurn: true, // burn because quorum not reached + expectedTally: v1.TallyResult{ + YesCount: "0", + AbstainCount: "0", + NoCount: "1000000", + NoWithVetoCount: "0", + }, + }, + { + name: "one account votes without delegation: prop fails/burn deposit", + setup: func(s suite) { + setTotalBonded(s, 10000000) + delegatorVote(s, s.delAddrs[0], nil, v1.VoteOption_VOTE_OPTION_YES) + }, + expectedPass: false, + expectedBurn: true, // burn because quorum not reached + expectedTally: v1.TallyResult{ + YesCount: "0", + AbstainCount: "0", + NoCount: "0", + NoWithVetoCount: "0", + }, + }, + { + name: "one delegator votes: prop fails/burn deposit", + setup: func(s suite) { + setTotalBonded(s, 10000000) + delegations := []stakingtypes.Delegation{{ + DelegatorAddress: s.delAddrs[0].String(), + ValidatorAddress: s.valAddrs[0].String(), + Shares: sdkmath.LegacyNewDec(42), + }} + delegatorVote(s, s.delAddrs[0], delegations, v1.VoteOption_VOTE_OPTION_YES) + }, + expectedPass: false, + expectedBurn: true, // burn because quorum not reached + expectedTally: v1.TallyResult{ + YesCount: "42", + AbstainCount: "0", + NoCount: "0", + NoWithVetoCount: "0", + }, + }, + { + name: "one delegator votes yes, validator votes also yes: prop fails/burn deposit", + setup: func(s suite) { + setTotalBonded(s, 10000000) + delegations := []stakingtypes.Delegation{{ + DelegatorAddress: s.delAddrs[0].String(), + ValidatorAddress: s.valAddrs[0].String(), + Shares: sdkmath.LegacyNewDec(42), + }} + delegatorVote(s, s.delAddrs[0], delegations, v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_YES) + }, + expectedPass: false, + expectedBurn: true, // burn because quorum not reached + expectedTally: v1.TallyResult{ + YesCount: "1000000", + AbstainCount: "0", + NoCount: "0", + NoWithVetoCount: "0", + }, + }, + { + name: "one delegator votes yes, validator votes no: prop fails/burn deposit", + setup: func(s suite) { + setTotalBonded(s, 10000000) + delegations := []stakingtypes.Delegation{{ + DelegatorAddress: s.delAddrs[0].String(), + ValidatorAddress: s.valAddrs[0].String(), + Shares: sdkmath.LegacyNewDec(42), + }} + delegatorVote(s, s.delAddrs[0], delegations, v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_NO) + }, + expectedPass: false, + expectedBurn: true, // burn because quorum not reached + expectedTally: v1.TallyResult{ + YesCount: "42", + AbstainCount: "0", + NoCount: "999958", + NoWithVetoCount: "0", + }, + }, + { + // one delegator delegates 42 shares to 2 different validators (21 each) + // delegator votes yes + // first validator votes yes + // second validator votes no + // third validator (no delegation) votes abstain + name: "delegator with mixed delegations: prop fails/burn deposit", + setup: func(s suite) { + setTotalBonded(s, 10000000) + delegations := []stakingtypes.Delegation{ + { + DelegatorAddress: s.delAddrs[0].String(), + ValidatorAddress: s.valAddrs[0].String(), + Shares: sdkmath.LegacyNewDec(21), + }, + { + DelegatorAddress: s.delAddrs[0].String(), + ValidatorAddress: s.valAddrs[1].String(), + Shares: sdkmath.LegacyNewDec(21), + }, + } + delegatorVote(s, s.delAddrs[0], delegations, v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_NO) + validatorVote(s, s.valAddrs[1], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[2], v1.VoteOption_VOTE_OPTION_ABSTAIN) + }, + expectedPass: false, + expectedBurn: true, // burn because quorum not reached + expectedTally: v1.TallyResult{ + YesCount: "1000021", + AbstainCount: "1000000", + NoCount: "999979", + NoWithVetoCount: "0", + }, + }, + { + name: "quorum reached with only abstain: prop fails", + setup: func(s suite) { + setTotalBonded(s, 10000000) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_ABSTAIN) + validatorVote(s, s.valAddrs[1], v1.VoteOption_VOTE_OPTION_ABSTAIN) + validatorVote(s, s.valAddrs[2], v1.VoteOption_VOTE_OPTION_ABSTAIN) + validatorVote(s, s.valAddrs[3], v1.VoteOption_VOTE_OPTION_ABSTAIN) + }, + expectedPass: false, + expectedBurn: false, + expectedTally: v1.TallyResult{ + YesCount: "0", + AbstainCount: "4000000", + NoCount: "0", + NoWithVetoCount: "0", + }, + }, + { + name: "quorum reached with veto>1/3: prop fails/burn deposit", + setup: func(s suite) { + setTotalBonded(s, 10000000) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[1], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[2], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[3], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[4], v1.VoteOption_VOTE_OPTION_NO_WITH_VETO) + validatorVote(s, s.valAddrs[5], v1.VoteOption_VOTE_OPTION_NO_WITH_VETO) + validatorVote(s, s.valAddrs[6], v1.VoteOption_VOTE_OPTION_NO_WITH_VETO) + }, + expectedPass: false, + expectedBurn: true, + expectedTally: v1.TallyResult{ + YesCount: "4000000", + AbstainCount: "0", + NoCount: "0", + NoWithVetoCount: "3000000", + }, + }, + { + name: "quorum reached with yes<=.5: prop fails", + setup: func(s suite) { + setTotalBonded(s, 10000000) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[1], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[2], v1.VoteOption_VOTE_OPTION_NO) + validatorVote(s, s.valAddrs[3], v1.VoteOption_VOTE_OPTION_NO) + }, + expectedPass: false, + expectedBurn: false, + expectedTally: v1.TallyResult{ + YesCount: "2000000", + AbstainCount: "0", + NoCount: "2000000", + NoWithVetoCount: "0", + }, + }, + { + name: "quorum reached with yes>.5: prop succeeds", + setup: func(s suite) { + setTotalBonded(s, 10000000) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[1], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[2], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[3], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[4], v1.VoteOption_VOTE_OPTION_NO) + validatorVote(s, s.valAddrs[5], v1.VoteOption_VOTE_OPTION_NO) + validatorVote(s, s.valAddrs[6], v1.VoteOption_VOTE_OPTION_NO_WITH_VETO) + }, + expectedPass: true, + expectedBurn: false, + expectedTally: v1.TallyResult{ + YesCount: "4000000", + AbstainCount: "0", + NoCount: "2000000", + NoWithVetoCount: "1000000", + }, + }, + { + name: "quorum reached thanks to abstain, yes>.5: prop succeeds", + setup: func(s suite) { + setTotalBonded(s, 10000000) + validatorVote(s, s.valAddrs[0], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[1], v1.VoteOption_VOTE_OPTION_YES) + validatorVote(s, s.valAddrs[2], v1.VoteOption_VOTE_OPTION_NO) + validatorVote(s, s.valAddrs[3], v1.VoteOption_VOTE_OPTION_ABSTAIN) + validatorVote(s, s.valAddrs[4], v1.VoteOption_VOTE_OPTION_ABSTAIN) + validatorVote(s, s.valAddrs[5], v1.VoteOption_VOTE_OPTION_ABSTAIN) + }, + expectedPass: true, + expectedBurn: false, + expectedTally: v1.TallyResult{ + YesCount: "2000000", + AbstainCount: "3000000", + NoCount: "1000000", + NoWithVetoCount: "0", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + govKeeper, mocks, _, ctx := setupGovKeeper(t, mockAccountKeeperExpectations) + params := v1.DefaultParams() + // Ensure params value are different than false + params.BurnVoteQuorum = true + params.BurnVoteVeto = true + err := govKeeper.SetParams(ctx, params) + require.NoError(t, err) + var ( + numVals = 10 + numDelegators = 5 + addrs = simtestutil.CreateRandomAccounts(numVals + numDelegators) + valAddrs = simtestutil.ConvertAddrsToValAddrs(addrs[:numVals]) + delAddrs = addrs[numVals:] + ) + // Mocks a bunch of validators + mocks.stakingKeeper.EXPECT(). + IterateBondedValidatorsByPower(ctx, gomock.Any()). + DoAndReturn( + func(ctx context.Context, fn func(index int64, validator stakingtypes.ValidatorI) bool) error { + for i := int64(0); i < int64(numVals); i++ { + fn(i, stakingtypes.Validator{ + OperatorAddress: valAddrs[i].String(), + Status: stakingtypes.Bonded, + Tokens: sdkmath.NewInt(1000000), + DelegatorShares: sdkmath.LegacyNewDec(1000000), + }) + } + return nil + }) + // Submit and activate a proposal + proposal, err := govKeeper.SubmitProposal(ctx, TestProposal, "", "title", "summary", delAddrs[0]) + require.NoError(t, err) + govKeeper.ActivateVotingPeriod(ctx, proposal) + suite := suite{ + t: t, + proposal: proposal, + valAddrs: valAddrs, + delAddrs: delAddrs, + ctx: ctx, + keeper: govKeeper, + mocks: mocks, + } + tt.setup(suite) + + pass, burn, tally := govKeeper.Tally(ctx, proposal) + + assert.Equal(t, tt.expectedPass, pass, "wrong pass") + assert.Equal(t, tt.expectedBurn, burn, "wrong burn") + assert.Equal(t, tt.expectedTally, tally) + }) + } +} diff --git a/x/gov/keeper/vote_test.go b/x/gov/keeper/vote_test.go index 048b75c3..0e4a665f 100644 --- a/x/gov/keeper/vote_test.go +++ b/x/gov/keeper/vote_test.go @@ -5,14 +5,17 @@ import ( "github.com/stretchr/testify/require" + sdkmath "cosmossdk.io/math" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" ) func TestVotes(t *testing.T) { - govKeeper, _, bankKeeper, stakingKeeper, _, ctx := setupGovKeeper(t) - addrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 2, sdk.NewInt(10000000)) + govKeeper, mocks, _, ctx := setupGovKeeper(t) + bankKeeper, stakingKeeper := mocks.bankKeeper, mocks.stakingKeeper + addrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 2, sdkmath.NewInt(10000000)) tp := TestProposal proposal, err := govKeeper.SubmitProposal(ctx, tp, "", "title", "description", sdk.AccAddress("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r"))