Skip to content

Commit 945803d

Browse files
sunnya97jaekwon
authored andcommitted
Governance Quorum (#3053)
1 parent 133134c commit 945803d

File tree

8 files changed

+40
-6
lines changed

8 files changed

+40
-6
lines changed

PENDING.md

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ FEATURES
3131
- [\#2961](https://github.com/cosmos/cosmos-sdk/issues/2961) Add --force flag to gaiacli keys delete command to skip passphrase check and force key deletion unconditionally.
3232

3333
* Gaia
34+
- [gov] Added minimum quorum needed for vote to pass
3435

3536
* SDK
3637

cmd/gaia/cmd/gaiareplay/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func run(rootDir string) {
131131
_ = proxyApp.Stop()
132132
}()
133133

134-
var state tmsm.State = tmsm.LoadState(tmDB)
134+
state := tmsm.LoadState(tmDB)
135135
if state.LastBlockHeight == 0 {
136136
// Send InitChain msg
137137
fmt.Println("Sending InitChain msg")

docs/spec/governance/overview.md

-4
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@ option that casts a `NoWithVeto` vote.*
111111
Quorum is defined as the minimum percentage of voting power that needs to be
112112
casted on a proposal for the result to be valid.
113113

114-
In the initial version of the governance module, there will be no quorum
115-
enforced by the protocol. Participation is ensured via the combination of
116-
inheritance and validator's punishment for non-voting.
117-
118114
### Threshold
119115

120116
Threshold is defined as the minimum proportion of `Yes` votes (excluding

docs/spec/governance/state.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type VotingParams struct {
2424

2525
```go
2626
type TallyParams struct {
27+
Quorum sdk.Dec // Minimum percentage of stake that needs to vote for a proposal to be considered valid
2728
Threshold sdk.Dec // Minimum proportion of Yes votes for proposal to pass. Initial value: 0.5
2829
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
2930
GovernancePenalty sdk.Dec // Penalty if validator does not vote

x/gov/genesis.go

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func DefaultGenesisState() GenesisState {
5151
VotingPeriod: time.Duration(172800) * time.Second,
5252
},
5353
TallyParams: TallyParams{
54+
Quorum: sdk.NewDecWithPrec(334, 3),
5455
Threshold: sdk.NewDecWithPrec(5, 1),
5556
Veto: sdk.NewDecWithPrec(334, 3),
5657
GovernancePenalty: sdk.NewDecWithPrec(1, 2),

x/gov/params.go

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type DepositParams struct {
1414

1515
// Param around Tallying votes in governance
1616
type TallyParams struct {
17+
Quorum sdk.Dec `json:"quorum"` // Minimum percentage of total stake needed to vote for a result to be considered valid
1718
Threshold sdk.Dec `json:"threshold"` // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
1819
Veto sdk.Dec `json:"veto"` // Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
1920
GovernancePenalty sdk.Dec `json:"governance_penalty"` // Penalty if validator does not vote

x/gov/tally.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,15 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
9393
NoWithVeto: results[OptionNoWithVeto],
9494
}
9595

96-
// If no one votes, proposal fails
96+
// If there is no staked coins, the proposal fails
97+
if keeper.vs.TotalPower(ctx).Equal(sdk.ZeroDec()) {
98+
return false, tallyResults
99+
}
100+
// If there is not enough quorum of votes, the proposal fails
101+
if totalVotingPower.Quo(keeper.vs.TotalPower(ctx)).LT(tallyParams.Quorum) {
102+
return false, tallyResults
103+
}
104+
// If no one votes (everyone abstains), proposal fails
97105
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroDec()) {
98106
return false, tallyResults
99107
}

x/gov/tally_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,32 @@ func TestTallyNoOneVotes(t *testing.T) {
5959
require.True(t, tallyResults.Equals(EmptyTallyResult()))
6060
}
6161

62+
func TestTallyNoQuorum(t *testing.T) {
63+
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
64+
mapp.BeginBlock(abci.RequestBeginBlock{})
65+
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
66+
stakeHandler := stake.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, stakeHandler, ctx, valAddrs, []int64{2, 5})
74+
stake.EndBlocker(ctx, sk)
75+
76+
proposal := keeper.NewTextProposal(ctx, "Test", "description", ProposalTypeText)
77+
proposalID := proposal.GetProposalID()
78+
proposal.SetStatus(StatusVotingPeriod)
79+
keeper.SetProposal(ctx, proposal)
80+
81+
err := keeper.AddVote(ctx, proposalID, addrs[0], OptionYes)
82+
require.Nil(t, err)
83+
84+
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
85+
require.False(t, passes)
86+
}
87+
6288
func TestTallyOnlyValidatorsAllYes(t *testing.T) {
6389
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
6490
mapp.BeginBlock(abci.RequestBeginBlock{})

0 commit comments

Comments
 (0)