# Messages ## Proposal Submission Proposals can be submitted by any Atom holder via a `TxGovSubmitProposal` transaction. ```go type TxGovSubmitProposal struct { Content Content InitialDeposit sdk.Coins Proposer sdk.AccAddress } ``` The `Content` of a `TxGovSubmitProposal` 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 `TxGovSubmitProposal` transaction can be handled according to the following pseudocode. ```go // PSEUDOCODE // // Check if TxGovSubmitProposal 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 = proposal.DepositEndTime = .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, , proposal) // Store proposal in Proposals mapping return proposalID ``` ## Deposit Once a proposal is submitted, if `Proposal.TotalDeposit < ActiveParam.MinDeposit`, Atom holders can send `TxGovDeposit` transactions to increase the proposal's deposit. ```go type TxGovDeposit struct { ProposalID int64 // ID of the proposal Deposit sdk.Coins // Number of Atoms to add to the proposal's deposit } ``` **State modifications:** - Decrease balance of sender by `deposit` - Add `deposit` of sender in `proposal.Deposits` - Increase `proposal.TotalDeposit` by sender's `deposit` - If `MinDeposit` is reached: - Push `proposalID` in `ProposalProcessingQueueEnd` - Transfer `Deposit` from the `proposer` to the governance `ModuleAccount` A `TxGovDeposit` transaction has to go through a number of checks to be valid. These checks are outlined in the following pseudocode. ```go // PSEUDOCODE // // Check if TxGovDeposit 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, ) // 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, , proposal) ``` ## Vote Once `ActiveParam.MinDeposit` is reached, voting period starts. From there, bonded Atom holders are able to send `TxGovVote` transactions to cast their vote on the proposal. ```go type TxGovVote struct { ProposalID int64 // proposalID of the proposal Vote byte // option from OptionSet chosen by the voter } ``` **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 proposal of the way `TxGovVote` transactions are handled: ```go // PSEUDOCODE // // Check if TxGovVote 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, ) 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.Vote) // Voters can vote multiple times. Re-voting overrides previous vote. This is ok because tallying is done once at the end. ```