Messages
Proposal Submission
Proposals can be submitted by any account via a MsgSubmitProposal
transaction.
// MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary
// proposal Content.
message MsgSubmitProposal {
option (cosmos.msg.v1.signer) = "proposer";
repeated google.protobuf.Any messages = 1;
repeated cosmos.base.v1beta1.Coin initial_deposit = 2 [(gogoproto.nullable) = false];
string proposer = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"];
// metadata is any arbitrary metadata attached to the proposal.
string metadata = 4;
}
All sdk.Msgs
passed into the messages
field of a MsgSubmitProposal
message must be registered in the app's MsgServiceRouter
. Each of these messages must have one signer, namely the gov module account. And finally, the metadata length must not be larger than the maxMetadataLen
config passed into the gov keeper.
State modifications:
Generate new
proposalID
Create new
Proposal
Initialise
Proposal
's attributesDecrease 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 and the messages have routes to other modules. Includes fee payment.
// check if all messages' unique Signer is the gov acct.
// check if the metadata is not too long.
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.Messages = txGovSubmitProposal.Messages
proposal.Metadata = txGovSubmitProposal.Metadata
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
Deposit
Once a proposal is submitted, if Proposal.TotalDeposit < ActiveParam.MinDeposit
, Atom holders can send MsgDeposit
transactions to increase the proposal's deposit.
// MsgDeposit defines a message to submit a deposit to an existing proposal.
message MsgDeposit {
option (cosmos.msg.v1.signer) = "depositor";
uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id"];
string depositor = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
repeated cosmos.base.v1beta1.Coin amount = 3 [(gogoproto.nullable) = false];
}
State modifications:
Decrease balance of sender by
deposit
Add
deposit
of sender inproposal.Deposits
Increase
proposal.TotalDeposit
by sender'sdeposit
If
MinDeposit
is reached:Push
proposalID
inProposalProcessingQueueEnd
Transfer
Deposit
from theproposer
to the governanceModuleAccount
A MsgDeposit
transaction has to go through a number of checks to be valid. These checks are outlined in the following pseudocode.
// PSEUDOCODE //
// Check if MsgDeposit is valid. If it is, increase deposit and check if MinDeposit is reached
upon receiving txGovDeposit from sender do
// check if proposal is correctly formatted. Includes fee payment.
if !correctlyFormatted(txGovDeposit)
throw
proposal = load(Proposals, <txGovDeposit.ProposalID|'proposal'>) // proposal is a const key, proposalID is variable
if (proposal == nil)
// There is no proposal for this proposalID
throw
if (txGovDeposit.Deposit.Atoms <= 0) OR (sender.AtomBalance < txGovDeposit.Deposit.Atoms) OR (proposal.CurrentStatus != ProposalStatusOpen)
// deposit is negative or null
// OR sender has insufficient funds
// OR proposal is not open for deposit anymore
throw
depositParam = load(GlobalParams, 'DepositParam')
if (CurrentBlock >= proposal.SubmitBlock + depositParam.MaxDepositPeriod)
proposal.CurrentStatus = ProposalStatusClosed
else
// sender can deposit
sender.AtomBalance -= txGovDeposit.Deposit.Atoms
proposal.Deposits.append({txGovVote.Deposit, sender})
proposal.TotalDeposit.Plus(txGovDeposit.Deposit)
if (proposal.TotalDeposit >= depositParam.MinDeposit)
// MinDeposit is reached, vote opens
proposal.VotingStartBlock = CurrentBlock
proposal.CurrentStatus = ProposalStatusActive
ProposalProcessingQueue.push(txGovDeposit.ProposalID)
store(Proposals, <txGovVote.ProposalID|'proposal'>, proposal)
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.
// MsgVote defines a message to cast a vote.
message MsgVote {
option (cosmos.msg.v1.signer) = "voter";
uint64 proposal_id = 1 [(gogoproto.jsontag) = "proposal_id"];
string voter = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"];
VoteOption option = 3;
string metadata = 4;
}
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.
Last updated