Submitting a Proposal
This page walks through submitting a governance proposal on AIOZ Network end-to-end, from preparing supporting material to depositing after submission. For what to propose, see Proposal Types; for the exact JSON shape, see Formatting a Proposal. If you haven't built community support yet, do that first: see Off-Chain Proposal Process.
Hosting Supplementary Materials
A title and description have to fit in a transaction, so keep them concise and host anything longer (full rationale, risk analysis, supporting data, discussion history) externally and link to it from the description. A public, durable location works best: a community forum post, a document pinned via AIOZ Pin, or a Telegram post that stays accessible.
Avoid linking to something only you can edit or take down later, a private doc, a message that can be deleted. Voters and anyone auditing the proposal afterward should be able to re-check exactly what they voted on, indefinitely.
Formatting the JSON File for the Governance Proposal
Every type other than Text needs a JSON proposal file rather than CLI flags alone. See Formatting a Proposal for the exact shape per type.
Validate the JSON locally before broadcasting; a malformed file fails the transaction outright and wastes the gas fee without the proposal ever entering the deposit period. A JSON linter or a quick jq . proposal.json is enough to catch syntax errors; catching semantic errors (wrong subspace, wrong field names) is what the testnet rehearsal at the end of this page is for.
Sending the Transaction That Submits Your Governance Proposal
A Text proposal can be submitted directly with flags, no file needed:
aiozd tx gov submit-legacy-proposal \
--title="<title>" \
--description="<description>" \
--type="Text" \
--deposit="1000000000000000000000attoaioz" \
--from=<key> \
--chain-id=<chain_id>For types that need a JSON file, the subcommand takes the file path instead of --type:
aiozd tx gov submit-legacy-proposal param-change <path/to/proposal.json> \
--from=<key> \
--chain-id=<chain_id>The pattern is the same across every type: aiozd tx gov submit-legacy-proposal <subcommand> <file> for anything with a JSON payload, aiozd tx gov submit-legacy-proposal --type=Text for anything without one.
The command is submit-legacy-proposal, not submit-proposal. Running aiozd tx gov --help against a real node confirms these are two distinct top-level subcommands: submit-proposal is the generic gov v1 path below, and submit-legacy-proposal is what every example on this page actually uses. The two are not interchangeable, submit-proposal param-change <file> fails with "no messages proposed" since it expects the newer messages array shape instead.
Proposal Types
Legacy Proposals (cosmos-sdk < v0.47)
AIOZ Network's aiozd currently exposes the legacy, content-based proposal interface shown throughout this section, reached via submit-legacy-proposal: --type="Text", param-change, community-pool-spend, each mounted as its own subcommand with a fixed, module-defined payload shape. This is the interface every example on this page uses, and the one that matches every proposal submitted on AIOZ mainnet to date.
Proposals (cosmos-sdk >= v0.47)
AIOZ mainnet's gov module also exposes a newer, generic Msg-based proposal interface, reached via the plain submit-proposal command (no legacy). It accepts a messages array of arbitrary proto-JSON-encoded Msgs, including a legacy Content type wrapped in MsgExecLegacyContent.
This was confirmed by generating an unsigned transaction against a real node: the old flat {title, changes, deposit} shape is rejected outright on this path.
Querying /cosmos/gov/v1/params/voting on the LCD shows this interface also carries parameters the legacy path doesn't:
expedited_voting_period(3 hours) andexpedited_threshold(66.7%), for proposals that opt into a shorter, higher-bar expedited trackproposal_cancel_ratioandmin_deposit_ratio, for finer control over deposit behavior
The proposal file itself has four top-level fields, confirmed by the exact JSON this interface accepted during testing:
title: the short name voters and block explorers will list the proposal under.summary: the full explanation of what's being proposed and why; unlike the legacy interface'sdescription, this is the field name the v1 schema actually validates against.deposit: the initial amount attached at submission, inattoaioz, same as the legacy path.metadata: typically a link to supplementary material hosted off-chain (a forum post, a pinned document via AIOZ Pin) rather than free-form text; see Hosting Supplementary Materials above.
messages sits alongside these four and carries the actual proto-JSON-encoded Msgs to execute if the proposal passes; it's what makes this interface generic rather than tied to a fixed set of content types.
aiozd query gov params and the LCD's /cosmos/gov/v1/params/voting route can disagree on which fields they return, depending on the aiozd build queried: an older CLI build returned only voting_params/tally_params/deposit_params with no expedited_* fields, while the LCD's v1 route returned the full parameter set including them. If you need the expedited parameters specifically, query the LCD route directly rather than relying on CLI output alone.
aiozd query gov paramsMinimal Deposit Amount
A proposal needs its total deposit to reach min_deposit before voting opens: currently 1000 AIOZ (1000000000000000000000attoaioz) on mainnet. This is a gov module parameter, not a constant, so it can itself change over a Parameter Change proposal; confirm the live value before submitting rather than trusting a number you saw a while ago:
aiozd query gov paramsWalkthrough Example (Changing x/staking Params)
Check the current value
Never assume the value you remember is still current:
aiozd query staking paramsWrite the proposal file
{
"title": "Increase max validators",
"description": "Raise the active validator set from 50 to 75",
"changes": [
{ "subspace": "staking", "key": "MaxValidators", "value": 75 }
],
"deposit": "1000000000000000000000attoaioz"
}The changes array can hold more than one entry if a single proposal needs to touch more than one parameter, though bundling unrelated changes into one proposal makes it harder for voters to evaluate and is usually best avoided.
Submit it
aiozd tx gov submit-legacy-proposal param-change proposal.json \
--from=<key> \
--chain-id=<chain_id>Confirm it entered the deposit period
aiozd query gov proposal <proposal_id>The returned status field should read PROPOSAL_STATUS_DEPOSIT_PERIOD if the deposit fell short of min_deposit, or PROPOSAL_STATUS_VOTING_PERIOD if it cleared it immediately.
Verifying Your Transaction
aiozd query tx <tx_hash>A successful submission returns code: 0 and includes the assigned proposal_id in its emitted events, under the submit_proposal event type. Save that ID immediately; it's what every subsequent command on this page needs.
Troubleshooting a Failed Transaction
- Non-zero
codein the tx result: read the accompanyingraw_log; a malformed JSON file or an invalidsubspace/keypair is the most common cause, and the log usually names the exact field. - Insufficient fees: re-check
--gas-pricesagainst the current network minimum; a transaction can be rejected at the mempool level before it ever reaches a block. - Proposal never leaves the deposit period: the deposit hasn't reached
min_deposityet; see the next section rather than resubmitting the same proposal again. account sequence mismatch: another transaction from the same key confirmed in between building and broadcasting this one; rebuild the transaction to pick up the current sequence number and resend.
Depositing Funds After a Proposal Has Been Submitted
Anyone can add to an existing proposal's deposit, not only the original proposer, which is useful when a proposer wants to gauge interest with a smaller initial amount rather than committing the full min_deposit up front:
aiozd tx gov deposit <proposal_id> "1000000000000000000000attoaioz" \
--from=<key> \
--chain-id=<chain_id>aiozd query gov deposits <proposal_id>If min_deposit isn't reached within max_deposit_period (2 days on mainnet), the proposal is dropped and every deposit already contributed, from every depositor, is burned rather than refunded.
Submitting Your Proposal to the Testnet
Rehearse the exact same proposal on AIOZ testnet before spending a real deposit on mainnet. Reusing the identical JSON file, only the chain-id and node change, is the point: it's a mechanical check that the payload itself is valid, not a test of a simplified version of it.
Get testnet AIOZ for the deposit and gas fees from the AIOZ Faucet (opens in a new tab) rather than needing a real balance.
aiozd tx gov submit-legacy-proposal param-change proposal.json \
--from=<key> \
--chain-id=aioztestnet_4102-2 \
--node=https://rpc-ds.testnet.aioz.network:443If it behaves as expected through a full deposit and voting cycle on testnet, that's a reasonable signal it will behave the same way on mainnet; the module logic doesn't differ between the two networks.