gov
Abstract
This paper specifies the Governance module
The module enables Cosmos-SDK based blockchain to support an on-chain governance system. In this system, holders of the native staking token of the chain can vote on proposals on a 1 token 1 vote basis. Next is a list of features the module currently supports:
- Proposal submission: Users can submit proposals with a deposit. Once the minimum deposit is reached, proposal enters voting period
- Vote: Participants can vote on proposals that reached MinDeposit
- Inheritance and penalties: Delegators inherit their validator's vote if they don't vote themselves.
- Claiming deposit: Users that deposited on proposals can recover their deposits if the proposal was accepted OR if the proposal never entered voting period.
This module will be used in the Cosmos Hub, the first Hub in the Cosmos network. Features that may be added in the future are described in [Future Improvements].
Contents
Concepts
Disclaimer: This is work in progress. Mechanisms are susceptible to change.
The governance process is divided in a few steps that are outlined below:
- Proposal submission: Proposal is submitted to the blockchain with a deposit.
- Vote: Once deposit reaches a certain value (
MinDeposit
), proposal is confirmed and vote opens. Bonded Atom holders can then sendTxGovVote
transactions to vote on the proposal. - If the proposal involves a software upgrade:
- Signal: Validators start signaling that they are ready to switch to the new version.
- Switch: Once more than 75% of validators have signaled that they are ready to switch, their software automatically flips to the new version.
Proposal submission
Right to submit a proposal
Any Dst holder, whether bonded or unbonded, can submit proposals by sending a
TxGovProposal
transaction. Once a proposal is submitted, it is identified by
its unique proposalID
.
Proposal types
In the initial version of the governance module, there are five types of proposals:
TextProposal
All the proposals that do not involve a modification of the source code go under this type. For example, an opinion poll would use a proposal of typeTextProposal
.SoftwareUpgradeProposal
. If accepted, validators are expected to update their software in accordance with the proposal. They must do so by following a 2-steps process described in the Software Upgrade section below. Software upgrade roadmap may be discussed and agreed on viaTextProposals
, but actual software upgrades must be performed viaSoftwareUpgradeProposals
.CommunityPoolSpendProposal
details a proposal for use of community funds, together with how many coins are proposed to be spent, and to which recipient account.ParameterChangeProposal
defines a proposal to change one or more parameters. If accepted, the requested parameter change is updated automatically by the proposal handler upon conclusion of the voting period.CancelSoftwareUpgradeProposal
is a gov Content type for cancelling a software upgrade.
Other modules may expand upon the governance module by implementing their own
proposal types and handlers. These types are registered and processed through the
governance module (eg. ParamChangeProposal
), which then execute the respective
module's proposal handler when a proposal passes. This custom handler may perform
arbitrary state changes.
Deposit
To prevent spam, proposals must be submitted with a deposit in the coins defined in the MinDeposit
param. The voting period will not start until the proposal's deposit equals MinDeposit
.
When a proposal is submitted, it has to be accompanied by a deposit that must be strictly positive, but can be inferior to MinDeposit
. The submitter doesn't need to pay for the entire deposit on their own. If a proposal's deposit is inferior to MinDeposit
, other token holders can increase the proposal's deposit by sending a Deposit
transaction. The deposit is kept in an escrow in the governance ModuleAccount
until the proposal is finalized (passed or rejected).
Once the proposal's deposit reaches MinDeposit
, it enters voting period. If proposal's deposit does not reach MinDeposit
before MaxDepositPeriod
, proposal closes and nobody can deposit on it anymore.
Deposit refund and burn
When a the a proposal finalized, the coins from the deposit are either refunded or burned, according to the final tally of the proposal:
- If the proposal is approved or if it's rejected but not vetoed, deposits will automatically be refunded to their respective depositor (transferred from the governance
ModuleAccount
). - When the proposal is vetoed with a supermajority, deposits be burned from the governance
ModuleAccount
.
Vote
Participants
Participants are users that have the right to vote on proposals. On the Cosmos Hub, participants are bonded Dst holders. Unbonded Atom holders and other users do not get the right to participate in governance. However, they can submit and deposit on proposals.
Note that some participants can be forbidden to vote on a proposal under a certain validator if:
- participant bonded or unbonded Dst to said validator after proposal entered voting period.
- participant became validator after proposal entered voting period.
This does not prevent participant to vote with Dst bonded to other validators. For example, if a participant bonded some Atoms to validator A before a proposal entered voting period and other Atoms to validator B after proposal entered voting period, only the vote under validator B will be forbidden.
Voting period
Once a proposal reaches MinDeposit
, it immediately enters Voting period
. We
define Voting period
as the interval between the moment the vote opens and
the moment the vote closes. Voting period
should always be shorter than
Unbonding period
to prevent double voting. The initial value of
Voting period
is 2 weeks.
Option set
The option set of a proposal refers to the set of choices a participant can choose from when casting its vote.
The initial option set includes the following options:
Yes
No
NoWithVeto
Abstain
NoWithVeto
counts as No
but also adds a Veto
vote. Abstain
option
allows voters to signal that they do not intend to vote in favor or against the
proposal but accept the result of the vote.
Note: from the UI, for urgent proposals we should maybe add a ‘Not Urgent’
option that casts a NoWithVeto
vote.
Quorum
Quorum is defined as the minimum percentage of voting power that needs to be casted on a proposal for the result to be valid.
Threshold
Threshold is defined as the minimum proportion of Yes
votes (excluding
Abstain
votes) for the proposal to be accepted.
Initially, the threshold is set at 50% with a possibility to veto if more than
1/3rd of votes (excluding Abstain
votes) are NoWithVeto
votes. This means
that proposals are accepted if the proportion of Yes
votes (excluding
Abstain
votes) at the end of the voting period is superior to 50% and if the
proportion of NoWithVeto
votes is inferior to 1/3 (excluding Abstain
votes).
Inheritance
If a delegator does not vote, it will inherit its validator vote.
- If the delegator votes before its validator, it will not inherit from the validator's vote.
- If the delegator votes after its validator, it will override its validator vote with its own. If the proposal is urgent, it is possible that the vote will close before delegators have a chance to react and override their validator's vote. This is not a problem, as proposals require more than 2/3rd of the total voting power to pass before the end of the voting period. If more than 2/3rd of validators collude, they can censor the votes of delegators anyway.
Validator’s punishment for non-voting
At present, validators are not punished for failing to vote.
Governance address
Later, we may add permissioned keys that could only sign txs from certain modules.
For the MVP, the Governance address
will be the main validator address generated at account creation.
This address corresponds to a different PrivKey than the Tendermint PrivKey which is responsible for signing consensus messages.
Validators thus do not have to sign governance transactions with the sensitive Tendermint PrivKey.
Software Upgrade
If proposals are of type SoftwareUpgradeProposal
, then nodes need to upgrade
their software to the new version that was voted. This process is divided in
two steps.
Signal
After a SoftwareUpgradeProposal
is accepted, validators are expected to
download and install the new version of the software while continuing to run
the previous version. Once a validator has downloaded and installed the
upgrade, it will start signaling to the network that it is ready to switch by
including the proposal's proposalID
in its precommits.(Note: Confirmation
that we want it in the precommit?)
Note: There is only one signal slot per precommit. If several
SoftwareUpgradeProposals
are accepted in a short timeframe, a pipeline will
form and they will be implemented one after the other in the order that they
were accepted.
Switch
Once a block contains more than 2/3rd precommits where a common
SoftwareUpgradeProposal
is signaled, all the nodes (including validator
nodes, non-validating full nodes and light-nodes) are expected to switch to the
new version of the software.
Note: Not clear how the flip is handled programmatically
State
Parameters and base types
Parameters
define the rules according to which votes are run. There can only
be one active parameter set at any given time. If governance wants to change a
parameter set, either to modify a value or add/remove a parameter field, a new
parameter set has to be created and the previous one rendered inactive.
DepositParams
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L127-L145
VotingParams
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L147-L156
TallyParams
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L158-L183
Parameters are stored in a global GlobalParams
KVStore.
Additionally, we introduce some basic types:
type Vote byte
const (
VoteYes = 0x1
VoteNo = 0x2
VoteNoWithVeto = 0x3
VoteAbstain = 0x4
)
type ProposalType string
const (
ProposalTypePlainText = "Text"
ProposalTypeSoftwareUpgrade = "SoftwareUpgrade"
)
type ProposalStatus byte
const (
StatusNil ProposalStatus = 0x00
StatusDepositPeriod ProposalStatus = 0x01 // Proposal is submitted. Participants can deposit on it but not vote
StatusVotingPeriod ProposalStatus = 0x02 // MinDeposit is reached, participants can vote
StatusPassed ProposalStatus = 0x03 // Proposal passed and successfully executed
StatusRejected ProposalStatus = 0x04 // Proposal has been rejected
StatusFailed ProposalStatus = 0x05 // Proposal passed but failed execution
)
Deposit
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L43-L53
ValidatorGovInfo
This type is used in a temp map when tallying
type ValidatorGovInfo struct {
Minus sdk.Dec
Vote Vote
}
Proposals
Proposal
objects are used to account votes and generally track the proposal's state. They contain Content
which denotes
what this proposal is about, and other fields, which are the mutable state of
the governance process.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/gov.proto#L55-L77
type Content interface {
GetTitle() string
GetDescription() string
ProposalRoute() string
ProposalType() string
ValidateBasic() sdk.Error
String() string
}
The Content
on a proposal is an interface which contains the information about
the Proposal
such as the tile, description, and any notable changes. Also, this
Content
type can by implemented by any module. The Content
's ProposalRoute
returns a string which must be used to route the Content
's Handler
in the
governance keeper. This allows the governance keeper to execute proposal logic
implemented by any module. If a proposal passes, the handler is executed. Only
if the handler is successful does the state get persisted and the proposal finally
passes. Otherwise, the proposal is rejected.
type Handler func(ctx sdk.Context, content Content) sdk.Error
The Handler
is responsible for actually executing the proposal and processing
any state changes specified by the proposal. It is executed only if a proposal
passes during EndBlock
.
We also mention a method to update the tally for a given proposal:
func (proposal Proposal) updateTally(vote byte, amount sdk.Dec)
Stores
Stores are KVStores in the multi-store. The key to find the store is the first parameter in the list`
We will use one KVStore Governance
to store two mappings:
- A mapping from
proposalID|'proposal'
toProposal
. - A mapping from
proposalID|'addresses'|address
toVote
. This mapping allows us to query all addresses that voted on the proposal along with their vote by doing a range query onproposalID:addresses
.
For pseudocode purposes, here are the two function we will use to read or write in stores:
load(StoreKey, Key)
: Retrieve item stored at keyKey
in store found at keyStoreKey
in the multistorestore(StoreKey, Key, value)
: Write valueValue
at keyKey
in store found at keyStoreKey
in the multistore
Proposal Processing Queue
Store:
ProposalProcessingQueue
: A queuequeue[proposalID]
containing all theProposalIDs
of proposals that reachedMinDeposit
. During eachEndBlock
, all the proposals that have reached the end of their voting period are processed. To process a finished proposal, the application tallies the votes, computes the votes of each validator and checks if every validator in the validator set has voted. If the proposal is accepted, deposits are refunded. Finally, the proposal contentHandler
is executed.
And the pseudocode for the ProposalProcessingQueue
:
in EndBlock do
for finishedProposalID in GetAllFinishedProposalIDs(block.Time)
proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
validators = Keeper.getAllValidators()
tmpValMap := map(sdk.AccAddress)ValidatorGovInfo
// Initiate mapping at 0. This is the amount of shares of the validator's vote that will be overridden by their delegator's votes
for each validator in validators
tmpValMap(validator.OperatorAddr).Minus = 0
// Tally
voterIterator = rangeQuery(Governance, <proposalID|'addresses'>) //return all the addresses that voted on the proposal
for each (voterAddress, vote) in voterIterator
delegations = stakingKeeper.getDelegations(voterAddress) // get all delegations for current voter
for each delegation in delegations
// make sure delegation.Shares does NOT include shares being unbonded
tmpValMap(delegation.ValidatorAddr).Minus += delegation.Shares
proposal.updateTally(vote, delegation.Shares)
_, isVal = stakingKeeper.getValidator(voterAddress)
if (isVal)
tmpValMap(voterAddress).Vote = vote
tallyingParam = load(GlobalParams, 'TallyingParam')
// Update tally if validator voted they voted
for each validator in validators
if tmpValMap(validator).HasVoted
proposal.updateTally(tmpValMap(validator).Vote, (validator.TotalShares - tmpValMap(validator).Minus))
// Check if proposal is accepted or rejected
totalNonAbstain := proposal.YesVotes + proposal.NoVotes + proposal.NoWithVetoVotes
if (proposal.Votes.YesVotes/totalNonAbstain > tallyingParam.Threshold AND proposal.Votes.NoWithVetoVotes/totalNonAbstain < tallyingParam.Veto)
// proposal was accepted at the end of the voting period
// refund deposits (non-voters already punished)
for each (amount, depositor) in proposal.Deposits
depositor.AtomBalance += amount
stateWriter, err := proposal.Handler()
if err != nil
// proposal passed but failed during state execution
proposal.CurrentStatus = ProposalStatusFailed
else
// proposal pass and state is persisted
proposal.CurrentStatus = ProposalStatusAccepted
stateWriter.save()
else
// proposal was rejected
proposal.CurrentStatus = ProposalStatusRejected
store(Governance, <proposalID|'proposal'>, proposal)
Messages
Proposal Submission
Proposals can be submitted by any account via a MsgSubmitProposal
transaction.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/tx.proto#L24-L39
The Content
of a MsgSubmitProposal
message must have an appropriate router
set in the governance module.
State modifications:
- Generate new
proposalID
- Create new
Proposal
- Initialise
Proposals
attributes - Decrease balance of sender by
InitialDeposit
- If
MinDeposit
is reached: - Push
proposalID
inProposalProcessingQueue
- Transfer
InitialDeposit
from theProposer
to the governanceModuleAccount
A MsgSubmitProposal
transaction can be handled according to the following
pseudocode.
// PSEUDOCODE //
// Check if MsgSubmitProposal is valid. If it is, create proposal //
upon receiving txGovSubmitProposal from sender do
if !correctlyFormatted(txGovSubmitProposal)
// check if proposal is correctly formatted. Includes fee payment.
throw
initialDeposit = txGovSubmitProposal.InitialDeposit
if (initialDeposit.Atoms <= 0) OR (sender.AtomBalance < initialDeposit.Atoms)
// InitialDeposit is negative or null OR sender has insufficient funds
throw
if (txGovSubmitProposal.Type != ProposalTypePlainText) OR (txGovSubmitProposal.Type != ProposalTypeSoftwareUpgrade)
sender.AtomBalance -= initialDeposit.Atoms
depositParam = load(GlobalParams, 'DepositParam')
proposalID = generate new proposalID
proposal = NewProposal()
proposal.Title = txGovSubmitProposal.Title
proposal.Description = txGovSubmitProposal.Description
proposal.Type = txGovSubmitProposal.Type
proposal.TotalDeposit = initialDeposit
proposal.SubmitTime = <CurrentTime>
proposal.DepositEndTime = <CurrentTime>.Add(depositParam.MaxDepositPeriod)
proposal.Deposits.append({initialDeposit, sender})
proposal.Submitter = sender
proposal.YesVotes = 0
proposal.NoVotes = 0
proposal.NoWithVetoVotes = 0
proposal.AbstainVotes = 0
proposal.CurrentStatus = ProposalStatusOpen
store(Proposals, <proposalID|'proposal'>, proposal) // Store proposal in Proposals mapping
return proposalID
Vote
Once ActiveParam.MinDeposit
is reached, voting period starts. From there,
bonded Atom holders are able to send MsgVote
transactions to cast their
vote on the proposal.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/gov/v1beta1/tx.proto#L46-L56
State modifications:
- Record
Vote
of sender
Note: Gas cost for this message has to take into account the future tallying of the vote in EndBlocker
Next is a pseudocode outline of the way MsgVote
transactions are
handled:
// PSEUDOCODE //
// Check if MsgVote is valid. If it is, count vote//
upon receiving txGovVote from sender do
// check if proposal is correctly formatted. Includes fee payment.
if !correctlyFormatted(txGovDeposit)
throw
proposal = load(Proposals, <txGovDeposit.ProposalID|'proposal'>)
if (proposal == nil)
// There is no proposal for this proposalID
throw
if (proposal.CurrentStatus == ProposalStatusActive)
// Sender can vote if
// Proposal is active
// Sender has some bonds
store(Governance, <txGovVote.ProposalID|'addresses'|sender>, txGovVote.Vote) // Voters can vote multiple times. Re-voting overrides previous vote. This is ok because tallying is done once at the end.
Events
The governance module emits the following events:
EndBlocker
Type | Attribute Key | Attribute Value |
---|---|---|
inactive_proposal | proposal_id | {proposalID} |
inactive_proposal | proposal_result | {proposalResult} |
active_proposal | proposal_id | {proposalID} |
active_proposal | proposal_result | {proposalResult} |
Handlers
MsgSubmitProposal
Type | Attribute Key | Attribute Value |
---|---|---|
submit_proposal | proposal_id | {proposalID} |
submit_proposal [0] | voting_period_start | {proposalID} |
proposal_deposit | amount | {depositAmount} |
proposal_deposit | proposal_id | {proposalID} |
message | module | governance |
message | action | submit_proposal |
message | sender | {senderAddress} |
- [0] Event only emitted if the voting period starts during the submission.
MsgVote
Type | Attribute Key | Attribute Value |
---|---|---|
proposal_vote | option | {voteOption} |
proposal_vote | proposal_id | {proposalID} |
message | module | governance |
message | action | vote |
message | sender | {senderAddress} |
MsgDeposit
Type | Attribute Key | Attribute Value |
---|---|---|
proposal_deposit | amount | {depositAmount} |
proposal_deposit | proposal_id | {proposalID} |
proposal_deposit [0] | voting_period_start | {proposalID} |
message | module | governance |
message | action | deposit |
message | sender | {senderAddress} |
- [0] Event only emitted if the voting period starts during the submission.
Parameters
The governance module contains the following parameters:
Key | Type | Example |
---|---|---|
depositparams | object | {"min_deposit":[{"denom":"uatom","amount":"10000000"}],"max_deposit_period":"172800000000000"} |
votingparams | object | {"voting_period":"172800000000000"} |
tallyparams | object | {"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto":"0.334000000000000000"} |
SubKeys
Key | Type | Example |
---|---|---|
min_deposit | array (coins) | [{"denom":"uatom","amount":"10000000"}] |
max_deposit_period | string (time ns) | "172800000000000" |
voting_period | string (time ns) | "172800000000000" |
quorum | string (dec) | "0.334000000000000000" |
threshold | string (dec) | "0.500000000000000000" |
veto | string (dec) | "0.334000000000000000" |
NOTE: The governance module contains parameters that are objects unlike other modules. If only a subset of parameters are desired to be changed, only they need to be included and not the entire parameter object structure.
Client
CLI
A user can query and interact with the gov
module using the CLI.
Query
The query
commands allow users to query gov
state.
simd query gov --help
deposit
The deposit
command allows users to query a deposit for a given proposal from a given depositor.
simd query gov deposit [proposal-id] [depositer-addr] [flags]
Example:
simd query gov deposit 1 cosmos1..
Example Output:
amount:
- amount: "100"
denom: stake
depositor: cosmos1..
proposal_id: "1"
deposits
The deposits
command allows users to query all deposits for a given proposal.
simd query gov deposits [proposal-id] [flags]
Example:
simd query gov deposits 1
Example Output:
deposits:
- amount:
- amount: "100"
denom: stake
depositor: cosmos1..
proposal_id: "1"
pagination:
next_key: null
total: "0"
param
The param
command allows users to query a given parameter for the gov
module.
simd query gov param [param-type] [flags]
Example:
simd query gov param voting
Example Output:
voting_period: "172800000000000"
params
The params
command allows users to query all parameters for the gov
module.
simd query gov params [flags]
Example:
simd query gov params
Example Output:
deposit_params:
max_deposit_period: "172800000000000"
min_deposit:
- amount: "10000000"
denom: stake
tally_params:
quorum: "0.334000000000000000"
threshold: "0.500000000000000000"
veto_threshold: "0.334000000000000000"
voting_params:
voting_period: "172800000000000"
proposal
The proposal
command allows users to query a given proposal.
simd query gov proposal [proposal-id] [flags]
Example:
simd query gov proposal 1
Example Output:
content:
'@type': /cosmos.gov.v1beta1.TextProposal
description: testing, testing, 1, 2, 3
title: Test Proposal
deposit_end_time: "2021-09-17T23:36:18.254995423Z"
final_tally_result:
abstain: "0"
"no": "0"
no_with_veto: "0"
"yes": "0"
proposal_id: "1"
status: PROPOSAL_STATUS_DEPOSIT_PERIOD
submit_time: "2021-09-15T23:36:18.254995423Z"
total_deposit:
- amount: "100"
denom: stake
voting_end_time: "0001-01-01T00:00:00Z"
voting_start_time: "0001-01-01T00:00:00Z"
proposals
The proposals
command allows users to query all proposals with optional filters.
simd query gov proposals [flags]
Example:
simd query gov proposals
Example Output:
pagination:
next_key: null
total: "1"
proposals:
- content:
'@type': /cosmos.gov.v1beta1.TextProposal
description: testing, testing, 1, 2, 3
title: Test Proposal
deposit_end_time: "2021-09-17T23:36:18.254995423Z"
final_tally_result:
abstain: "0"
"no": "0"
no_with_veto: "0"
"yes": "0"
proposal_id: "1"
status: PROPOSAL_STATUS_DEPOSIT_PERIOD
submit_time: "2021-09-15T23:36:18.254995423Z"
total_deposit:
- amount: "100"
denom: stake
voting_end_time: "0001-01-01T00:00:00Z"
voting_start_time: "0001-01-01T00:00:00Z"
proposer
The proposer
command allows users to query the proposer for a given proposal.
simd query gov proposer [proposal-id] [flags]
Example:
simd query gov proposer 1
Example Output:
proposal_id: "1"
proposer: cosmos1r0tllwu5c9dtgwg3wr28lpvf76hg85f5zmh9l2
tally
The tally
command allows users to query the tally of a given proposal vote.
simd query gov tally [proposal-id] [flags]
Example:
simd query gov tally 1
Example Output:
abstain: "0"
"no": "0"
no_with_veto: "0"
"yes": "1"
vote
The vote
command allows users to query a vote for a given proposal.
simd query gov vote [proposal-id] [voter-addr] [flags]
Example:
simd query gov vote 1 cosmos1..
Example Output:
option: VOTE_OPTION_YES
options:
- option: VOTE_OPTION_YES
weight: "1.000000000000000000"
proposal_id: "1"
voter: cosmos1..
votes
The votes
command allows users to query all votes for a given proposal.
simd query gov votes [proposal-id] [flags]
Example:
simd query gov votes 1
Example Output:
pagination:
next_key: null
total: "0"
votes:
- option: VOTE_OPTION_YES
options:
- option: VOTE_OPTION_YES
weight: "1.000000000000000000"
proposal_id: "1"
voter: cosmos1r0tllwu5c9dtgwg3wr28lpvf76hg85f5zmh9l2
Transactions
The tx
commands allow users to interact with the gov
module.
simd tx gov --help
deposit
The deposit
command allows users to deposit tokens for a given proposal.
simd tx gov deposit [proposal-id] [deposit] [flags]
Example:
simd tx gov deposit 1 10000000stake --from cosmos1..
submit-proposal
The submit-proposal
command allows users to submit a governance proposal and to optionally include an initial deposit.
simd tx gov submit-proposal [command] [flags]
Example:
simd tx gov submit-proposal --title="Test Proposal" --description="testing, testing, 1, 2, 3" --type="Text" --deposit="10000000stake" --from cosmos1..
Example (cancel-software-upgrade
):
simd tx gov submit-proposal cancel-software-upgrade --title="Test Proposal" --description="testing, testing, 1, 2, 3" --deposit="10000000stake" --from cosmos1..
Example (community-pool-spend
):
simd tx gov submit-proposal community-pool-spend proposal.json --from cosmos1..
{
"title": "Test Proposal",
"description": "testing, testing, 1, 2, 3",
"recipient": "cosmos1..",
"amount": "10000000stake",
"deposit": "10000000stake"
}
Example (param-change
):
simd tx gov submit-proposal param-change proposal.json --from cosmos1..
{
"title": "Test Proposal",
"description": "testing, testing, 1, 2, 3",
"changes": [
{
"subspace": "staking",
"key": "MaxValidators",
"value": 100
}
],
"deposit": "10000000stake"
}
Example (software-upgrade
):
simd tx gov submit-proposal software-upgrade v2 --title="Test Proposal" --description="testing, testing, 1, 2, 3" --upgrade-height 1000000 --from cosmos1..
vote
The vote
command allows users to submit a vote for a given governance proposal.
simd tx gov vote [command] [flags]
Example:
simd tx gov vote 1 yes --from cosmos1..
weighted-vote
The weighted-vote
command allows users to submit a weighted vote for a given governance proposal.
simd tx gov weighted-vote [proposal-id] [weighted-options]
Example:
simd tx gov weighted-vote 1 yes=0.5,no=0.5 --from cosmos1
gRPC
A user can query the gov
module using gRPC endpoints.
Proposal
The Proposal
endpoint allows users to query a given proposal.
cosmos.gov.v1beta1.Query/Proposal
Example:
grpcurl -plaintext \
-d '{"proposal_id":"1"}' \
localhost:9090 \
cosmos.gov.v1beta1.Query/Proposal
Example Output:
{
"proposal": {
"proposalId": "1",
"content": {"@type":"/cosmos.gov.v1beta1.TextProposal","description":"testing, testing, 1, 2, 3","title":"Test Proposal"},
"status": "PROPOSAL_STATUS_VOTING_PERIOD",
"finalTallyResult": {
"yes": "0",
"abstain": "0",
"no": "0",
"noWithVeto": "0"
},
"submitTime": "2021-09-16T19:40:08.712440474Z",
"depositEndTime": "2021-09-18T19:40:08.712440474Z",
"totalDeposit": [
{
"denom": "stake",
"amount": "10000000"
}
],
"votingStartTime": "2021-09-16T19:40:08.712440474Z",
"votingEndTime": "2021-09-18T19:40:08.712440474Z"
}
}
Proposals
The Proposals
endpoint allows users to query all proposals with optional filters.
cosmos.gov.v1beta1.Query/Proposals
Example:
grpcurl -plaintext \
localhost:9090 \
cosmos.gov.v1beta1.Query/Proposals
Example Output:
{
"proposals": [
{
"proposalId": "1",
"content": {"@type":"/cosmos.gov.v1beta1.TextProposal","description":"testing, testing, 1, 2, 3","title":"Test Proposal"},
"status": "PROPOSAL_STATUS_VOTING_PERIOD",
"finalTallyResult": {
"yes": "0",
"abstain": "0",
"no": "0",
"noWithVeto": "0"
},
"submitTime": "2021-09-16T19:40:08.712440474Z",
"depositEndTime": "2021-09-18T19:40:08.712440474Z",
"totalDeposit": [
{
"denom": "stake",
"amount": "10000000"
}
],
"votingStartTime": "2021-09-16T19:40:08.712440474Z",
"votingEndTime": "2021-09-18T19:40:08.712440474Z"
},
{
"proposalId": "2",
"content": {"@type":"/cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal","description":"Test Proposal","title":"testing, testing, 1, 2, 3"},
"status": "PROPOSAL_STATUS_DEPOSIT_PERIOD",
"finalTallyResult": {
"yes": "0",
"abstain": "0",
"no": "0",
"noWithVeto": "0"
},
"submitTime": "2021-09-17T18:26:57.866854713Z",
"depositEndTime": "2021-09-19T18:26:57.866854713Z",
"votingStartTime": "0001-01-01T00:00:00Z",
"votingEndTime": "0001-01-01T00:00:00Z"
}
],
"pagination": {
"total": "2"
}
}
Vote
The Vote
endpoint allows users to query a vote for a given proposal.
cosmos.gov.v1beta1.Query/Vote
Example:
grpcurl -plaintext \
-d '{"proposal_id":"1","voter":"cosmos1.."}' \
localhost:9090 \
cosmos.gov.v1beta1.Query/Vote
Example Output:
{
"vote": {
"proposalId": "1",
"voter": "cosmos1..",
"option": "VOTE_OPTION_YES",
"options": [
{
"option": "VOTE_OPTION_YES",
"weight": "1000000000000000000"
}
]
}
}
Votes
The Votes
endpoint allows users to query all votes for a given proposal.
cosmos.gov.v1beta1.Query/Votes
Example:
grpcurl -plaintext \
-d '{"proposal_id":"1"}' \
localhost:9090 \
cosmos.gov.v1beta1.Query/Votes
Example Output:
{
"votes": [
{
"proposalId": "1",
"voter": "cosmos1..",
"option": "VOTE_OPTION_YES",
"options": [
{
"option": "VOTE_OPTION_YES",
"weight": "1000000000000000000"
}
]
}
],
"pagination": {
"total": "1"
}
}
Params
The Params
endpoint allows users to query all parameters for the gov
module.
cosmos.gov.v1beta1.Query/Params
Example:
grpcurl -plaintext \
-d '{"params_type":"voting"}' \
localhost:9090 \
cosmos.gov.v1beta1.Query/Params
Example Output:
{
"votingParams": {
"votingPeriod": "172800s"
},
"depositParams": {
"maxDepositPeriod": "0s"
},
"tallyParams": {
"quorum": "MA==",
"threshold": "MA==",
"vetoThreshold": "MA=="
}
}
Deposit
The Deposit
endpoint allows users to query a deposit for a given proposal from a given depositor.
cosmos.gov.v1beta1.Query/Deposit
Example:
grpcurl -plaintext \
'{"proposal_id":"1","depositor":"cosmos1.."}' \
localhost:9090 \
cosmos.gov.v1beta1.Query/Deposit
Example Output:
{
"deposit": {
"proposalId": "1",
"depositor": "cosmos1..",
"amount": [
{
"denom": "stake",
"amount": "10000000"
}
]
}
}
deposits
The Deposits
endpoint allows users to query all deposits for a given proposal.
cosmos.gov.v1beta1.Query/Deposits
Example:
grpcurl -plaintext \
-d '{"proposal_id":"1"}' \
localhost:9090 \
cosmos.gov.v1beta1.Query/Deposits
Example Output:
{
"deposits": [
{
"proposalId": "1",
"depositor": "cosmos1..",
"amount": [
{
"denom": "stake",
"amount": "10000000"
}
]
}
],
"pagination": {
"total": "1"
}
}
TallyResult
The TallyResult
endpoint allows users to query the tally of a given proposal.
cosmos.gov.v1beta1.Query/TallyResult
Example:
grpcurl -plaintext \
-d '{"proposal_id":"1"}' \
localhost:9090 \
cosmos.gov.v1beta1.Query/TallyResult
Example Output:
{
"tally": {
"yes": "1000000",
"abstain": "0",
"no": "0",
"noWithVeto": "0"
}
}
REST
A user can query the gov
module using REST endpoints.
proposal
The proposals
endpoint allows users to query a given proposal.
/cosmos/gov/v1beta1/proposals/{proposal_id}
Example:
curl localhost:1317/cosmos/gov/v1beta1/proposals/1
Example Output:
{
"proposal": {
"proposal_id": "1",
"content": {
"@type": "/cosmos.gov.v1beta1.TextProposal",
"title": "Test Proposal",
"description": "testing, testing, 1, 2, 3"
},
"status": "PROPOSAL_STATUS_VOTING_PERIOD",
"final_tally_result": {
"yes": "0",
"abstain": "0",
"no": "0",
"no_with_veto": "0"
},
"submit_time": "2021-09-16T19:40:08.712440474Z",
"deposit_end_time": "2021-09-18T19:40:08.712440474Z",
"total_deposit": [
{
"denom": "stake",
"amount": "10000000"
}
],
"voting_start_time": "2021-09-16T19:40:08.712440474Z",
"voting_end_time": "2021-09-18T19:40:08.712440474Z"
}
}
proposals
The proposals
endpoint also allows users to query all proposals with optional filters.
/cosmos/gov/v1beta1/proposals
Example:
curl localhost:1317/cosmos/gov/v1beta1/proposals
Example Output:
{
"proposals": [
{
"proposal_id": "1",
"content": {
"@type": "/cosmos.gov.v1beta1.TextProposal",
"title": "Test Proposal",
"description": "testing, testing, 1, 2, 3"
},
"status": "PROPOSAL_STATUS_VOTING_PERIOD",
"final_tally_result": {
"yes": "0",
"abstain": "0",
"no": "0",
"no_with_veto": "0"
},
"submit_time": "2021-09-16T19:40:08.712440474Z",
"deposit_end_time": "2021-09-18T19:40:08.712440474Z",
"total_deposit": [
{
"denom": "stake",
"amount": "10000000"
}
],
"voting_start_time": "2021-09-16T19:40:08.712440474Z",
"voting_end_time": "2021-09-18T19:40:08.712440474Z"
},
{
"proposal_id": "2",
"content": {
"@type": "/cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal",
"title": "Test Proposal",
"description": "testing, testing, 1, 2, 3"
},
"status": "PROPOSAL_STATUS_DEPOSIT_PERIOD",
"final_tally_result": {
"yes": "0",
"abstain": "0",
"no": "0",
"no_with_veto": "0"
},
"submit_time": "2021-09-17T18:26:57.866854713Z",
"deposit_end_time": "2021-09-19T18:26:57.866854713Z",
"total_deposit": [
],
"voting_start_time": "0001-01-01T00:00:00Z",
"voting_end_time": "0001-01-01T00:00:00Z"
}
],
"pagination": {
"next_key": null,
"total": "2"
}
}
voter vote
The votes
endpoint allows users to query a vote for a given proposal.
/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}
Example:
curl localhost:1317/cosmos/gov/v1beta1/proposals/1/votes/cosmos1..
Example Output:
{
"vote": {
"proposal_id": "1",
"voter": "cosmos1..",
"option": "VOTE_OPTION_YES",
"options": [
{
"option": "VOTE_OPTION_YES",
"weight": "1.000000000000000000"
}
]
}
}
votes
The votes
endpoint allows users to query all votes for a given proposal.
/cosmos/gov/v1beta1/proposals/{proposal_id}/votes
Example:
curl localhost:1317/cosmos/gov/v1beta1/proposals/1/votes
Example Output:
{
"votes": [
{
"proposal_id": "1",
"voter": "cosmos1..",
"option": "VOTE_OPTION_YES",
"options": [
{
"option": "VOTE_OPTION_YES",
"weight": "1.000000000000000000"
}
]
}
],
"pagination": {
"next_key": null,
"total": "1"
}
}
params
The params
endpoint allows users to query all parameters for the gov
module.
/cosmos/gov/v1beta1/params/{params_type}
Example:
curl localhost:1317/cosmos/gov/v1beta1/params/voting
Example Output:
{
"voting_params": {
"voting_period": "172800s"
},
"deposit_params": {
"min_deposit": [
],
"max_deposit_period": "0s"
},
"tally_params": {
"quorum": "0.000000000000000000",
"threshold": "0.000000000000000000",
"veto_threshold": "0.000000000000000000"
}
}
deposits
The deposits
endpoint allows users to query a deposit for a given proposal from a given depositor.
/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}
Example:
curl localhost:1317/cosmos/gov/v1beta1/proposals/1/deposits/cosmos1..
Example Output:
{
"deposit": {
"proposal_id": "1",
"depositor": "cosmos1..",
"amount": [
{
"denom": "stake",
"amount": "10000000"
}
]
}
}
proposal deposits
The deposits
endpoint allows users to query all deposits for a given proposal.
/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits
Example:
curl localhost:1317/cosmos/gov/v1beta1/proposals/1/deposits
Example Output:
{
"deposits": [
{
"proposal_id": "1",
"depositor": "cosmos1..",
"amount": [
{
"denom": "stake",
"amount": "10000000"
}
]
}
],
"pagination": {
"next_key": null,
"total": "1"
}
}
tally
The tally
endpoint allows users to query the tally of a given proposal.
/cosmos/gov/v1beta1/proposals/{proposal_id}/tally
Example:
curl localhost:1317/cosmos/gov/v1beta1/proposals/1/tally
Example Output:
{
"tally": {
"yes": "1000000",
"abstain": "0",
"no": "0",
"no_with_veto": "0"
}
}