Skip to content

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 send TxGovVote 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 type TextProposal.
  • 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 via TextProposals, but actual software upgrades must be performed via SoftwareUpgradeProposals.
  • 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' to Proposal.
  • A mapping from proposalID|'addresses'|address to Vote. This mapping allows us to query all addresses that voted on the proposal along with their vote by doing a range query on proposalID: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 key Key in store found at key StoreKey in the multistore
  • store(StoreKey, Key, value): Write value Value at key Key in store found at key StoreKey in the multistore

Proposal Processing Queue

Store:

  • ProposalProcessingQueue: A queue queue[proposalID] containing all the ProposalIDs of proposals that reached MinDeposit. During each EndBlock, 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 content Handler 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 in ProposalProcessingQueue
  • Transfer InitialDeposit from the Proposer to the governance ModuleAccount

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"
  }
}