diff --git a/x/gov/keeper/tally.go b/x/gov/keeper/tally.go index 2d06d945..42f1494d 100644 --- a/x/gov/keeper/tally.go +++ b/x/gov/keeper/tally.go @@ -1,6 +1,8 @@ package keeper import ( + "fmt" + "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -64,6 +66,7 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal v1.Proposal) (passes bool, results[option.Option] = results[option.Option].Add(subPower) } totalVotingPower = totalVotingPower.Add(votingPower) + fmt.Println("ADD VOTE", votingPower) } return false @@ -78,6 +81,7 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal v1.Proposal) (passes bool, if len(val.Vote) == 0 { continue } + fmt.Println("VAL DEL SHARES", val.DelegatorShares, val.DelegatorDeductions) sharesAfterDeductions := val.DelegatorShares.Sub(val.DelegatorDeductions) votingPower := sharesAfterDeductions.MulInt(val.BondedTokens).Quo(val.DelegatorShares) @@ -88,6 +92,7 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal v1.Proposal) (passes bool, results[option.Option] = results[option.Option].Add(subPower) } totalVotingPower = totalVotingPower.Add(votingPower) + fmt.Println("ADD VAL VOTE", votingPower) } params := keeper.GetParams(ctx) @@ -96,6 +101,7 @@ 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 totalBondedTokens := keeper.sk.TotalBondedTokens(ctx) + fmt.Println("total bonded", totalBondedTokens) if totalBondedTokens.IsZero() { return false, false, tallyResults } diff --git a/x/gov/keeper/tally_test.go b/x/gov/keeper/tally_test.go index 1af0c030..9e237f9c 100644 --- a/x/gov/keeper/tally_test.go +++ b/x/gov/keeper/tally_test.go @@ -30,13 +30,15 @@ func TestTally(t *testing.T) { } var ( + totalBonded int64 // 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) + // Increment total bonded according to each delegations + for _, d := range delegations { + totalBonded += d.Shares.RoundInt64() + } s.mocks.stakingKeeper.EXPECT(). IterateDelegations(s.ctx, voter, gomock.Any()). DoAndReturn( @@ -48,8 +50,14 @@ func TestTally(t *testing.T) { }) } validatorVote = func(s suite, voter sdk.ValAddress, vote v1.VoteOption) { - // validatorVote is like delegatorVote but without delegations - delegatorVote(s, sdk.AccAddress(voter), nil, vote) + accAddr := sdk.AccAddress(voter) + // validator self delegation + selfDelegation := []stakingtypes.Delegation{{ + DelegatorAddress: accAddr.String(), + ValidatorAddress: voter.String(), + Shares: sdkmath.LegacyNewDec(1), + }} + delegatorVote(s, accAddr, selfDelegation, vote) } ) tests := []struct { @@ -61,10 +69,7 @@ func TestTally(t *testing.T) { expectedError string }{ { - name: "no votes, no bonded tokens: prop fails", - setup: func(s suite) { - setTotalBonded(s, 0) - }, + name: "no votes, no bonded tokens: prop fails", expectedPass: false, expectedBurn: false, expectedTally: v1.TallyResult{ @@ -75,10 +80,7 @@ func TestTally(t *testing.T) { }, }, { - name: "no votes: prop fails/burn deposit", - setup: func(s suite) { - setTotalBonded(s, 10000000) - }, + name: "no votes: prop fails/burn deposit", expectedPass: false, expectedBurn: true, // burn because quorum not reached expectedTally: v1.TallyResult{ @@ -91,7 +93,6 @@ func TestTally(t *testing.T) { { 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, @@ -106,7 +107,6 @@ func TestTally(t *testing.T) { { 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, @@ -121,7 +121,6 @@ func TestTally(t *testing.T) { { 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(), @@ -141,7 +140,6 @@ func TestTally(t *testing.T) { { 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(), @@ -162,7 +160,6 @@ func TestTally(t *testing.T) { { 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(), @@ -188,7 +185,6 @@ func TestTally(t *testing.T) { // 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(), @@ -218,7 +214,6 @@ func TestTally(t *testing.T) { { 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) @@ -236,7 +231,6 @@ func TestTally(t *testing.T) { { 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) @@ -257,7 +251,6 @@ func TestTally(t *testing.T) { { 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) @@ -275,7 +268,6 @@ func TestTally(t *testing.T) { { 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) @@ -296,7 +288,6 @@ func TestTally(t *testing.T) { { 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) @@ -323,6 +314,12 @@ func TestTally(t *testing.T) { params.BurnVoteVeto = true err := govKeeper.SetParams(ctx, params) require.NoError(t, err) + // Reset total bonded + totalBonded = 0 + mocks.stakingKeeper.EXPECT().TotalBondedTokens(gomock.Any()). + DoAndReturn(func(_ context.Context) sdkmath.Int { + return sdkmath.NewInt(totalBonded) + }).MaxTimes(1) var ( numVals = 10 numDelegators = 5 @@ -339,8 +336,8 @@ func TestTally(t *testing.T) { fn(i, stakingtypes.Validator{ OperatorAddress: valAddrs[i].String(), Status: stakingtypes.Bonded, - Tokens: sdkmath.NewInt(1000000), - DelegatorShares: sdkmath.LegacyNewDec(1000000), + Tokens: sdkmath.NewInt(totalBonded), + DelegatorShares: sdkmath.LegacyNewDec(totalBonded), }) } return nil @@ -358,13 +355,16 @@ func TestTally(t *testing.T) { keeper: govKeeper, mocks: mocks, } - tt.setup(suite) + if tt.setup != nil { + 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) + assert.Empty(t, govKeeper.GetVotes(ctx, proposal.Id), "votes not be removed after tally") }) } }