github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/gov/keeper/tally_test.go (about) 1 package keeper 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/fibonacci-chain/fbc/x/common" 8 9 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 10 "github.com/stretchr/testify/require" 11 12 "github.com/fibonacci-chain/fbc/x/gov/types" 13 "github.com/fibonacci-chain/fbc/x/staking" 14 ) 15 16 func newTallyResult(t *testing.T, totalVoted, yes, abstain, no, veto, totalVoting string) types.TallyResult { 17 decTotalVoting, err := sdk.NewDecFromStr(totalVoting) 18 require.Nil(t, err) 19 decTotalVoted, err := sdk.NewDecFromStr(totalVoted) 20 require.Nil(t, err) 21 decYes, err := sdk.NewDecFromStr(yes) 22 require.Nil(t, err) 23 decAbstain, err := sdk.NewDecFromStr(abstain) 24 require.Nil(t, err) 25 decNo, err := sdk.NewDecFromStr(no) 26 require.Nil(t, err) 27 decNoWithVeto, err := sdk.NewDecFromStr(veto) 28 require.Nil(t, err) 29 return types.TallyResult{ 30 TotalPower: decTotalVoting, 31 TotalVotedPower: decTotalVoted, 32 Yes: decYes, 33 Abstain: decAbstain, 34 No: decNo, 35 NoWithVeto: decNoWithVeto, 36 } 37 } 38 39 func TestTallyNoBondedTokens(t *testing.T) { 40 ctx, _, keeper, _, _ := CreateTestInput(t, false, 1000) 41 42 content := types.NewTextProposal("Test", "description") 43 proposal, err := keeper.SubmitProposal(ctx, content) 44 require.Nil(t, err) 45 46 proposal.Status = types.StatusVotingPeriod 47 keeper.SetProposal(ctx, proposal) 48 49 // less quorum when expire VotingPeriod 50 status, dist, tallyResults := Tally(ctx, keeper, proposal, true) 51 require.False(t, dist) 52 require.Equal(t, types.StatusRejected, status) 53 require.True(t, tallyResults.Equals(types.EmptyTallyResult(keeper.totalPower(ctx)))) 54 55 // less quorum when in VotingPeriod 56 status, dist, tallyResults = Tally(ctx, keeper, proposal, false) 57 require.False(t, dist) 58 require.Equal(t, types.StatusRejected, status) 59 require.True(t, tallyResults.Equals(types.EmptyTallyResult(keeper.totalPower(ctx)))) 60 } 61 62 func TestTallyNoOneVotes(t *testing.T) { 63 ctx, _, keeper, sk, _ := CreateTestInput(t, false, 100000) 64 65 ctx.SetBlockHeight(int64(sk.GetEpoch(ctx))) 66 stakingHandler := staking.NewHandler(sk) 67 68 valAddrs := make([]sdk.ValAddress, len(Addrs[:2])) 69 for i, addr := range Addrs[:2] { 70 valAddrs[i] = sdk.ValAddress(addr) 71 } 72 73 CreateValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 5}) 74 staking.EndBlocker(ctx, sk) 75 76 content := types.NewTextProposal("Test", "description") 77 proposal, err := keeper.SubmitProposal(ctx, content) 78 require.Nil(t, err) 79 80 proposal.Status = types.StatusVotingPeriod 81 keeper.SetProposal(ctx, proposal) 82 83 // less quorum when expire VotingPeriod 84 status, dist, tallyResults := Tally(ctx, keeper, proposal, true) 85 require.True(t, dist) 86 require.Equal(t, types.StatusRejected, status) 87 require.True(t, tallyResults.Equals(types.EmptyTallyResult(keeper.totalPower(ctx)))) 88 89 // less quorum when in VotingPeriod 90 status, dist, tallyResults = Tally(ctx, keeper, proposal, false) 91 require.False(t, dist) 92 require.Equal(t, types.StatusVotingPeriod, status) 93 require.True(t, tallyResults.Equals(types.EmptyTallyResult(keeper.totalPower(ctx)))) 94 } 95 96 func TestTallyAllValidatorsVoteAbstain(t *testing.T) { 97 ctx, _, keeper, sk, _ := CreateTestInput(t, false, 100000) 98 99 ctx.SetBlockHeight(int64(sk.GetEpoch(ctx))) 100 stakingHandler := staking.NewHandler(sk) 101 102 valAddrs := make([]sdk.ValAddress, len(Addrs[:2])) 103 for i, addr := range Addrs[:2] { 104 valAddrs[i] = sdk.ValAddress(addr) 105 } 106 107 CreateValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 5}) 108 staking.EndBlocker(ctx, sk) 109 110 content := types.NewTextProposal("Test", "description") 111 proposal, err := keeper.SubmitProposal(ctx, content) 112 require.Nil(t, err) 113 114 proposal.Status = types.StatusVotingPeriod 115 keeper.SetProposal(ctx, proposal) 116 117 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[0], types.OptionAbstain) 118 require.Nil(t, err) 119 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[1], types.OptionAbstain) 120 require.Nil(t, err) 121 122 expectedTallyResult := newTallyResult(t, "2", "0.0", "2", "0.0", "0.0", "2") 123 // when expire VotingPeriod 124 status, dist, tallyResults := Tally(ctx, keeper, proposal, true) 125 require.False(t, dist) 126 require.Equal(t, types.StatusRejected, status) 127 require.True(t, tallyResults.Equals(expectedTallyResult)) 128 129 // when in VotingPeriod 130 status, dist, tallyResults = Tally(ctx, keeper, proposal, false) 131 require.False(t, dist) 132 require.Equal(t, types.StatusRejected, status) 133 require.True(t, tallyResults.Equals(expectedTallyResult)) 134 } 135 136 // test more than one third validator vote veto, in this test there are two validators 137 // and one vote veto. 138 func TestTallyAllValidatorsMoreThanOneThirdVeto(t *testing.T) { 139 ctx, _, keeper, sk, _ := CreateTestInput(t, false, 100000) 140 141 ctx.SetBlockHeight(int64(sk.GetEpoch(ctx))) 142 stakingHandler := staking.NewHandler(sk) 143 144 valAddrs := make([]sdk.ValAddress, len(Addrs[:2])) 145 for i, addr := range Addrs[:2] { 146 valAddrs[i] = sdk.ValAddress(addr) 147 } 148 149 CreateValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 5}) 150 staking.EndBlocker(ctx, sk) 151 152 content := types.NewTextProposal("Test", "description") 153 proposal, err := keeper.SubmitProposal(ctx, content) 154 require.Nil(t, err) 155 156 proposal.Status = types.StatusVotingPeriod 157 keeper.SetProposal(ctx, proposal) 158 159 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[0], types.OptionNoWithVeto) 160 require.Nil(t, err) 161 162 expectedTallyResult := newTallyResult(t, "1", "0.0", "0.0", "0.0", "1", "2") 163 // when expire VotingPeriod 164 status, dist, tallyResults := Tally(ctx, keeper, proposal, true) 165 require.True(t, dist) 166 require.Equal(t, types.StatusRejected, status) 167 require.True(t, tallyResults.Equals(expectedTallyResult)) 168 169 // when in VotingPeriod 170 status, dist, tallyResults = Tally(ctx, keeper, proposal, false) 171 require.True(t, dist) 172 require.Equal(t, types.StatusRejected, status) 173 require.True(t, tallyResults.Equals(expectedTallyResult)) 174 } 175 176 func TestTallyOtherCase(t *testing.T) { 177 ctx, _, keeper, sk, _ := CreateTestInput(t, false, 100000) 178 ctx.SetBlockHeight(int64(sk.GetEpoch(ctx))) 179 stakingHandler := staking.NewHandler(sk) 180 valAddrs := make([]sdk.ValAddress, len(Addrs[:2])) 181 for i, addr := range Addrs[:2] { 182 valAddrs[i] = sdk.ValAddress(addr) 183 } 184 CreateValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 5}) 185 staking.EndBlocker(ctx, sk) 186 187 content := types.NewTextProposal("Test", "description") 188 proposal, err := keeper.SubmitProposal(ctx, content) 189 require.Nil(t, err) 190 proposal.Status = types.StatusVotingPeriod 191 keeper.SetProposal(ctx, proposal) 192 193 // one of two validators vote no, that is more than or equal to 1/2 of non-abstain vote not Yes 194 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[0], types.OptionNo) 195 require.Nil(t, err) 196 197 expectedTallyResult := newTallyResult(t, "1", "0.0", "0.0", "1", "0.0", "2") 198 // when expire VotingPeriod 199 status, dist, tallyResults := Tally(ctx, keeper, proposal, true) 200 require.False(t, dist) 201 require.Equal(t, types.StatusRejected, status) 202 require.True(t, tallyResults.Equals(expectedTallyResult)) 203 204 // when in VotingPeriod 205 status, dist, tallyResults = Tally(ctx, keeper, proposal, false) 206 require.False(t, dist) 207 require.Equal(t, types.StatusRejected, status) 208 require.True(t, tallyResults.Equals(expectedTallyResult)) 209 210 // all validators vote yes, that is more than to 1/2 of non-abstain vote Yes when expire VotingPeriod 211 // and more than 2/3 of totalBonded vote Yes when in VotingPeriod 212 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[0], types.OptionYes) 213 require.Nil(t, err) 214 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[1], types.OptionYes) 215 require.Nil(t, err) 216 217 expectedTallyResult = newTallyResult(t, "2", "2", "0.0", "0.0", "0.0", "2") 218 // when expire VotingPeriod 219 status, dist, tallyResults = Tally(ctx, keeper, proposal, true) 220 require.False(t, dist) 221 require.Equal(t, types.StatusPassed, status) 222 require.True(t, tallyResults.Equals(expectedTallyResult)) 223 224 // when in VotingPeriod 225 status, dist, tallyResults = Tally(ctx, keeper, proposal, false) 226 require.False(t, dist) 227 require.Equal(t, types.StatusPassed, status) 228 require.True(t, tallyResults.Equals(expectedTallyResult)) 229 } 230 231 func TestTallyDelegatorInherit(t *testing.T) { 232 ctx, _, keeper, sk, _ := CreateTestInput(t, false, 100000) 233 ctx.SetBlockHeight(int64(sk.GetEpoch(ctx))) 234 ctx.SetBlockTime(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)) 235 stakingHandler := staking.NewHandler(sk) 236 valAddrs := make([]sdk.ValAddress, len(Addrs[:3])) 237 for i, addr := range Addrs[:3] { 238 valAddrs[i] = sdk.ValAddress(addr) 239 } 240 CreateValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 5, 5}) 241 staking.EndBlocker(ctx, sk) 242 243 coin, err := sdk.ParseDecCoin("11000.0" + common.NativeToken) 244 require.Nil(t, err) 245 delegator1Msg := staking.NewMsgDeposit(Addrs[3], coin) 246 stakingHandler(ctx, delegator1Msg) 247 248 addSharesMsg := staking.NewMsgAddShares(Addrs[3], []sdk.ValAddress{sdk.ValAddress(Addrs[2])}) 249 stakingHandler(ctx, addSharesMsg) 250 251 content := types.NewTextProposal("Test", "description") 252 proposal, err := keeper.SubmitProposal(ctx, content) 253 require.Nil(t, err) 254 proposal.Status = types.StatusVotingPeriod 255 keeper.SetProposal(ctx, proposal) 256 257 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[0], types.OptionNo) 258 require.Nil(t, err) 259 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[1], types.OptionNo) 260 require.Nil(t, err) 261 err, _ = keeper.AddVote(ctx, proposal.ProposalID, Addrs[2], types.OptionYes) 262 require.Nil(t, err) 263 264 // there are 3 validators with 1 voting power for each one (0.001fibo -> 1 power) 265 // 2 vals -> OptionNo 266 // 1 val -> OptionYes 267 expectedTallyResult := newTallyResult(t, "11003", "11001", "0.0", "2", "0.0", "11003") 268 status, dist, tallyResults := Tally(ctx, keeper, proposal, true) 269 require.False(t, dist) 270 require.Equal(t, types.StatusPassed, status) 271 require.Equal(t, expectedTallyResult, tallyResults) 272 } 273 274 func TestTallyDelegatorOverride(t *testing.T) { 275 ctx, _, keeper, sk, _ := CreateTestInput(t, false, 100000) 276 ctx.SetBlockHeight(int64(sk.GetEpoch(ctx))) 277 ctx.SetBlockTime(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)) 278 stakingHandler := staking.NewHandler(sk) 279 valAddrs := make([]sdk.ValAddress, len(Addrs[:3])) 280 for i, addr := range Addrs[:3] { 281 valAddrs[i] = sdk.ValAddress(addr) 282 } 283 CreateValidators(t, stakingHandler, ctx, valAddrs, []int64{5, 5, 5}) 284 staking.EndBlocker(ctx, sk) 285 286 coin, err := sdk.ParseDecCoin("1.0" + common.NativeToken) 287 require.Nil(t, err) 288 delegator1Msg := staking.NewMsgDeposit(Addrs[3], coin) 289 stakingHandler(ctx, delegator1Msg) 290 291 addSharesMsg := staking.NewMsgAddShares(Addrs[3], []sdk.ValAddress{sdk.ValAddress(Addrs[2])}) 292 stakingHandler(ctx, addSharesMsg) 293 294 content := types.NewTextProposal("Test", "description") 295 proposal, err := keeper.SubmitProposal(ctx, content) 296 require.Nil(t, err) 297 proposal.Status = types.StatusVotingPeriod 298 keeper.SetProposal(ctx, proposal) 299 proposalID := proposal.ProposalID 300 301 err, _ = keeper.AddVote(ctx, proposalID, Addrs[0], types.OptionYes) 302 require.Nil(t, err) 303 err, _ = keeper.AddVote(ctx, proposalID, Addrs[1], types.OptionYes) 304 require.Nil(t, err) 305 err, _ = keeper.AddVote(ctx, proposalID, Addrs[2], types.OptionYes) 306 require.Nil(t, err) 307 err, _ = keeper.AddVote(ctx, proposalID, Addrs[3], types.OptionNo) 308 require.Nil(t, err) 309 310 expectedTallyResult := newTallyResult(t, "4", "3", "0.0", "1", "0.0", "4") 311 status, dist, tallyResults := Tally(ctx, keeper, proposal, true) 312 require.False(t, dist) 313 require.Equal(t, types.StatusPassed, status) 314 require.Equal(t, expectedTallyResult, tallyResults) 315 }