🔲Blocks and Transactions
This document describes the block and transaction structure of the Cronos POS Chain and explains different ways to extract and parse the details of them.
Table of Content
Common APIs
Tendermint
Common APIs
Tendermint
1. Tendermint Block API
URL format: https://rpc.mainnet.crypto.org/block?height=[height]
This API returns block details, a list of transaction bytes and consensus commits.
Example: Checking the block at height 10000
of the mainnet:
https://rpc.mainnet.crypto.org/block?height=10000
2. Tendermint Block Results API
URL format: https://rpc.mainnet.crypto.org:26657/block_results?height=[height]
This API returns the events of the block. These events include the outcomes from transactions, and block changes such as block rewards minted (
"mint"
) and distributed as well as consensus state updates such as validator missing block counts ("liveness"
)
Example: Checking the block result of height 10000
of the mainnet:
https://rpc.mainnet.crypto.org/block_results?height=10000
Cosmos
3. Cosmos Transaction Query API
URL format: https://rpc.mainnet.crypto.org/comsos/tx/v1beta1/txs/[Transaction_Hash]
This API returns the parsed transaction details and events of a particular transaction hash
Example: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/0C5E617B0577B047D78EBF5313B8B70DF69E9535E17B964303BD04947B11B660
4. Cosmos Transaction Search API
URL format: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs
This API support event-based query and returns parsed transactions. Common events include:
message.module & message.action
Search for messages belonged to a particular module and actions. Note that this index will degrade when more transaction of its kind grows in number
message.sender
Search for message with particular signer
Note:
The API supports pagination, make sure you have iterate all the pages
pagination.offset=[offset starting from 0]&pagination.limit=[record per page]
The performance will degrade if you are searching for a result set that will grow over time. For example, if we search for events that grow with the block height, such as validator's reward distrubtion.
Multiple events in a single search are queried by
AND
condition. i.e If you dotx.height
andmessage.sender
. It will search for transactions that happened on that particular block height AND signed by the sender.
Common Block Details
Most of the block events can be accessed using the Tendermint Block Results API. One caveat of using this API is that all the events key-value attributes are base64 encoded. Therefore it is non-human readable.
A simple Node.js tool has been written to help parse and decode all key-value attributes in the block results API response. It can be downloaded at https://github.com/calvinaco/cosmos-api-tools.
Usage example:
Note that when you integrate with the API you should still base64 decode the attributes programmatically.
1. Mint
In every block, CRO is minted and offered to the active validators and their delegators as block rewards. The actual minted token is subject to inflation and is adjusted every block. Further details on the minting parameters and configuration can be found here.
Minted tokens are distributed as blocks and proposer rewards in the same block. However, since Cosmos SDK does the lazy rewards calculation and collection, the minted tokens are first sent to the "Distribution" module account and are later transferred to an account when a delegator withdraws the rewards or commissions by sending a MsgWithdrawDelegatorReward or MsgWithdrawValidatorCommission.
So Block Rewards, Proposer Rewards and Commissions events are for record-keeping only and do not represent any actual token transfer between accounts.
To get the minted token every block:
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "mint" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "amount"
2. Block Rewards
In every block, mint tokens and transaction fees are distributed to every active validator in the network. As a result, there will be multiple events, each corresponding to a validator and the rewards it receives.
Block rewards are not credited to the delegator account directly. This event serves as a record-keeping purpose only. Each delegator account must explicitly send a MsgWithdrawDelegatorReward message transaction to collect the rewards.
To get the reward per validator:
Validator Address
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "rewards" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "validator"
Reward Amount
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "rewards" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "amount"
String
3. Proposer Rewards
Block proposers can get extra transaction fees bonus for the block they have successfully proposed. More details can be found here for reference.
Similar to block rewards, proposer rewards are not credited to the account directly. This event serves as a record-keeping purpose only. Each validator creator account must explicitly send a MsgWithdrawDelegatorReward message transaction to collect the rewards.
Validator Address
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "proposer_reward" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "validator"
Reward Amount
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "proposer_reward" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "amount"
String
4. Commissions
Validator can charge a commission to the block rewards received by delegators. Commissions is already included in Block Rewards and Proposer Rewards
Similar to block rewards, commission rewards are not credited to the account directly. This event serves as a record-keeping purpose only. Each validator creator account must explicitly send a MsgWithdrawValidatorCommission message transaction to collect the rewards.
To get the commission received by each validator:
Validator Address
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "rewards" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "validator"
Commission Amount
Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].value)
where
Base64Decode(result.begin_block_events[event_index].type) === "rewards" && Base64Decode(result.begin_block_events[event_index].attributes[attribute_index].key) === "amount"
String
Common Transaction Details
1. Block Height
Tendermint Block API:
result.block.header.height
Tendermint Block Results API:
result.height
Cosmos Transaction Query API:
tx_response.height
Cosmos Transaction Search API:
tx_response[index].height
2. Transaction Hash
Tendermint Block API:
Uppercase(SHA256(Base64Decode(result.block.data.txs[index])))
Tendermint Block Results API: Not available, should use Tendermint Block API. Match transaction
[index]
inresult.txs_results
withresult.block.data.txs[index]
Cosmos Transaction Query API:
tx_response.txhash
Cosmos Transaction Search API:
tx_response[index].txhash
3. Transaction Fee
Cosmos Transaction Query API:
tx.auth_info.fee.amount
Cosmos Transaction Search API:
tx[index].auth_info.fee.amount
Transaction fee is an Asset Array, meaning that a transaction can pay fee in more than one token types.
4. Assets and Amount
There are mainly two types of assets and amount representation:
1. Single object
This is commonly seen in staking
module but may appear in other modules as well. It represents a single token type.
Example
where denom
is the asset type and amount
is the amount and basecro
is the basic unit of CRO token (where 10^8 basecro
= 1 cro)
Note that the amount
is always in string for precision accuracy. Please make sure your language is capable of handling big integer numbers. It is highly recommended to use library similar to bignumber.js in your language to handle the amount
.
2. Array
This is commonly seen in most message types. It represents a list of tokens.
At the time of writing, there will only be a single entry in this array because basecro
(or basetcro
in Croeseid Testnet) is the only supported asset on Cronos POS Chain. However, after IBC transfer and other coins issuance methods are enabled, there will be more asset types, the coin source tracing and their denomination can be found here
Example:
Each object in the array has the same format as Single Object.
3. String
This is commonly seen in events' attributes of block and transaction.
Example:
Bank
1. MsgSend
Descriptions: Simple transfer message
Funds movement: Yes
Protobuf Structure
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/0C5E617B0577B047D78EBF5313B8B70DF69E9535E17B964303BD04947B11B660
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.bank.v1beta1.MsgSend"
String
From address
tx.body.messages[message_index].from_address
String
To address
tx.body.messages[message_index].to_address
String
2. MsgMultiSend
Descriptions: Multiple inputs, multiple outputs transfer message.
Funds movement: Yes
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/6CD89C9F32A4F4E918B2BCD722A9429693E3372E3F882BA4A460F2588A2EE0B3
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.bank.v1beta1.MsgMultiSend"
String
From Addresses
tx.body.messages[message_index].inputs[m].address
where m>=1
. There can be multiple (m
) from addresses.
String
From Amounts
tx.body.messages[message_index].inputs[m].coins
where m>=1
. There can be multiple (m
) from addresses and their corresponding input amount.
To Addresses
tx.body.messages[message_index].outputs[n].address
where n>=1
. There can be multiple (n
) destination addresses.
String
To Amounts
tx.body.messages[message_index].outputs[n].coins
where n>=1
. There can be multiple (n
) destination addresses and their corresponding input amount.
Distribution
1. MsgSetWithdrawAddress
Descriptions: Sets the withdraw address for a delegator (or validator self-delegation)
Funds movement: No (Pay for fee only)
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/D4FCC8E1403677157D367A88A0832B9E411BDC4E029954FC133DB60296CF3DE3
Details
TODO
2. MsgWithdrawDelegatorReward
Descriptions: Withdraw delegation rewards from a single validator
Funds movement: Yes
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/3B36AA1AC81ACD58E7A06C21353DB0FC40A70EDBF6BD2CD23D7BEDC7A0F56318
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward"
String
Delegator
tx.body.messages[message_index].delegator_address
String
Withdraw From Validator
tx.body.messages[message_index].validator_address
String
Withdraw To Address
tx_response.logs[message_index].events[event_index].attributes[attribute_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "recipient"
.
String
Withdraw Reward Amount
tx_response.logs[message_index].events[event_index].attributes[attribute_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "amount"
.
3. MsgWithdrawValidatorCommission
Descriptions: : Withdraws the full commission of a validator to the validator creator (initial delegator) address.
Funds movement: Yes
Protofbuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/3739F76EF67A61D6F0163A5B177EA64ED80B67D9AEF8435C525913E69026D320
Message Index:
1
Details
This transaction will trigger an internal transfer from the "Distribution" module account to the withdraw to address. Note that the "Distribution" module account is an internal account in Cronos POS Chain to hold the rewards, commissions and community pool funds before they are being distributed.
The "Distribution" module account is different on different chain. In Cronos POS Chain Mainnet, it is cro1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8lyv94w.
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission"
String
Validator
tx.body.messages[message_index].validator_address
String
Withdraw From Validator
tx.body.messages[message_index].validator_address
String
Withdraw To Address
tx_response.logs[message_index].events[event_index].attributes[attribute_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "recipient"
.
String
Withdraw Commission Amount
tx_response.logs[message_index].events[event_index].attributes[m].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "amount"
.
4. MsgFundCommunityPool
Descriptions: : Fund from an account to the community pool. The community pool can later be sent to another by submitting a MsgSubmitEcProposal
Funds movement: Yes
Protobuf
Example: A transaction funding the community pool
https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/7C1747E0189DCA88BBA55A1720809C8DF6075799C11ECBE4C4E1F89C91D4F55F
Details
This transaction will initiate a transfer from an account to the "Distribution" module account. Note that the "Distribution" module account is an internal account in Cronos POS Chain to hold the rewards, commissions and community pool funds before they are being distributed.
This "Distribution" module account is different on different chain. In Cronos POS Chain Mainnet, it is cro1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8lyv94w.
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.distribution.v1beta1.MsgFundCommunityPool"
String
Deposit From Account
tx.body.messages[message_index].depositor
String
Delegate To Address ("Distribution" module account)
tx_response.logs[message_index].events[event_index].attributes[attribute_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "recipient"
.
String
Staking
1. MsgCreateValidator
Descriptions: : Create a new validator
Funds movement: Yes
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/7B3C19A3674C9EF856C43FFF50B021085AC4DA693AA47F82882FFAC78F21DE05
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.staking.v1beta1.MsgCreateValidator"
String
Initial Delegator Address (Validator Creator)
tx.body.messages[message_index].delegator_address
String
2. MsgEditValidator
Descriptions: Edit and existing validator
Funds Movement: No (Pay for fee only)
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/F4A1D7757AD20979D540C0CD29DD335D17E121F15AA447990B87E0EE94531BD7
Details
TODO
3. MsgDelegate
Descriptions: Perform a delegation of coins from a delegator to a validator
Funds movement: Yes
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/CCB45B0C6EC18A327ADFC8C36478A163D8C2A8BD9EB13687F73ED3D4559318A3
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.staking.v1beta1.MsgDelegate"
String
Delegate From Address
tx.body.messages[message_index].delegator_address
String
Delegate To Validator
tx.body.messages[message_index].validator_address
String
4. MsgBeginRedelegate
Descriptions: Perform a redelegation of coins from a delegator and source validator to a destination validator.
Note that the redelegation is just a record update of the internal state of a delegator's staked funds. The delegator account won't have any funds movement based on the redelegation except.
There is a side effect of
MsgBeginRedelegate
, upon successful execution of this message, all the rewards of the delegator from the previous (source) validator will be withdrawn automatically to the delegator account.Funds movement: Yes
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/5D43A55463C8FB30A89306C26C5E3318826AD075D36E9B5E72F7019C00F14549
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.staking.v1beta1.MsgBeginRedelegate"
String
Redelegate From Address
tx.body.messages[message_index].delegator_address
String
Redelegate From Validator
tx.body.messages[message_index].validator_src_address
String
Redelegate To Validator
tx.body.messages[message_index].validator_dst_address
String
Auto Withdraw Rewards To Address #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "recipient"
.
String
Auto Withdraw Rewards From Address (Always the "distribution" module account) #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "sender"
.
String
Auto Withdraw Rewards Amount #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "amount"
.
String
Note: There may be multiple auto reward withdrawals that happen. In such a case, the transfer
event will have multiple {"recipient":"","sender":"","amount":""}
. An example is
5. MsgUndelegate
Descriptions: Perform an undelegation from a delegate and a validator.
Note that the funds are moved between module accounts upon a
MsgUndelegate
message execution. The funds movement to the user account happens only when the unbond completes. For details, you can refer to the next section.Funds movement: Yes
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/3B36AA1AC81ACD58E7A06C21353DB0FC40A70EDBF6BD2CD23D7BEDC7A0F56318
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.distribution.v1beta1.MsgFundCommunityPool"
String
Undelegate From Address
tx.body.messages[message_index].delegator_address
String
Undelegate From Validator
tx.body.messages[message_index].validator_src_address
String
Auto Withdraw Rewards To Address #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "recipient"
.
String
Auto Withdraw Rewards From Address (Always the "distribution" module account) #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "sender"
.
String
Auto Withdraw Rewards Amount #
tx_response.logs[message_index].events[event_index].value
where
tx_response.logs[message_index].events[event_index].type === "transfer" && tx_response.logs[message_index].events[event_index].attributes[attribute_index].key === "amount"
.
String
Note: Similar to MsgBeginRedelegate, there may be multiple auto reward withdrawals happen. In such a case the transfer
event will have the multiple {"recipient":"","sender":"","amount":""}
5a. Upon MsgUndelegate completed
Descriptions: The undelegation is completed on the first block after the "Unbond Completion Time", in which there will be a special event in the Tendermint Block Results API.
Funds movement: Yes
Example
Tendermint Block Results API: https://rpc.mainnet.crypto.org/block_results?height=374823
Details
Undelegate From Validator
.result.end_block_events[event_index].attributes[attribute_index].value
where
.result.end_block_events[event_index].type === "complete_unbonding" && .result.end_block_events[event_index].attributes[attribute_index].key === "validator"
.
String
Undelegate To Address
.result.end_block_events[event_index].attributes[attribute_index].value
where
.result.end_block_events[event_index].type === "complete_unbonding" && .result.end_block_events[event_index].attributes[attribute_index].key === "delegator"
.
String
Undeleate Amount
.result.end_block_events[event_index].attributes[attribute_index].value
where
.result.end_block_events[event_index].type === "complete_unbonding" && .result.end_block_events[event_index].attributes[attribute_index].key === "amount"
.
Slashing
1. MsgUnjail
Descriptions: : Unjail a validator
Funds movement: No (Pay for fee only)
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/58BF8EBD17FF9500F395E4A9B2AE93EF21306E5706B3EC31CE116654D78B8684
Details
TODO
2. Being Jailed and Slashed
A validator can get jailed for two reasons:
Liveness
Double sign
Liveness
Liveness issue occurs when the validator fails to sign 50%* of the blocks in a 5000# blocks sliding window.
Upon a validator committing a liveness issue, the validator is jailed for 24 hours (85400 seconds#).
# The liveness metrics and the penalty are subject to the network parameters to be explained in the details section
Double Sign
Double sign occurs when a validator attempts to provide multiple signatures of the same block height.
This is considered as a serious fault and upon committing the validator will get jailed forever and get slashed for 5% of the total staking#.
This slashing is applied to all the delegations (both self delegation and delegation from other accounts).
# The slashing rate is subject to the network parameters to be explained in the details section
Limitations
There is a limitation in the protocol that the slashing amount cannot be easily extracted right now. Theoretically one could calculate the slashed amount of each delegator by applying the slash rate and delegation proportion but in practice small precision issues may be introduced in the calculation process and introduce discrepancies with the chain, so it is not recommended to do so.
On the other hand, the slashed amount, similar to the block rewards and commission, is not deducted from delegator account directly. There are events to signal the jail and slashing occurs but it serve more of the purpose of describing such as event occurs only.
Details - Params
Cosmos Slashing Params API: https://rpc.mainnet.crypto.org/cosmos/slashing/v1beta1/params
Signing window size (in Blocks)
Liveness
.params.signed_blocks_window
String
Minimum # of blocks to sign in the window
Liveness
.params.min_signed_per_window
String
How long to jail
Liveness
.params.downtime_jail_duration
String (Duration)
Slashing ratio
Liveness
.params.slash_fraction_downtime
String
Slashing ratio
Double Sign
.params.slash_fraction_double_sign
String
Details - Jail and Slash events
Tendermint Block Results API: https://rpc.mainnet.crypto.org/block?height=[height]
You can use the Cosmos API tools to decode the event details for readability during integration.
Jail
Liveness, Double Sign
.results.begin_block_events[event_index].type === "slash" && Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].key) === "jailed"
Assertion
Jailed Reason
Liveness
Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].value === "missing_signature"
where
.results.begin_block_events[event_index].type === "slash" && Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].key) === "reason"
String
Jailed Reason
Double Sign
Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].value === "double_sign"
where
.results.begin_block_events[event_index].type === "slash" && Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].key) === "reason"
String
Jailed Validator Address
Liveness, Double Sign
Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].value)
where
.results.begin_block_events[event_index].type === "slash" && Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].key) === "jailed"
String
Slashed Validator Address
Liveness, Double Sign
Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].value)
where
.results.begin_block_events[event_index].type === "slash" && Base64Decode(.results.begin_block_events[event_index].attributes[attribute_index].key) === "address"
String
Liveness Example: [https://rpc.mainnet.crypto.org/block_results?height=210356]
Liveness Event Example
Double Sign Example: https://rpc.mainnet.crypto.org/block_results?height=210356
Double Sign Event Example
Governance
1. MsgSubmitProposal
Submit proposal
Initial deposit will transfer from the proposer account to the "gov" module account.
Funds movement: Yes
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/9CCC988616344C804E8831B6FC6BECD6FD0F815E4E3FF13BDE6B7F8360BF0050
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.gov.v1beta1.MsgSubmitProposal"
String
Deposit From Address
tx.body.messages[message_index].porposer
String
1a. Community Pool Spend Proposal
One sub-type of proposal is to spend community pool. The community has to pre-funded using MsgFundCommunityPool.
After a proposal of this kind is passed, it will release the funds to the grants recipient account.
Community Pool Spend Proposal Transaction
Proposal Type
tx.body.messages[message_index].content["@type"] === "/cosmos.distribution.v1beta1.CommunityPoolSpendProposal"
String
Grants Recipient Address
tx.body.messages[message_index].conbtent.recipient
String
Example of Community Pool Spend Proposal transaction:
Community Pool Spend Proposal Funds Movement
Proposal Passed
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value) === "proposal_passed"
where
.result.end_block_events[event_index].type === "active_proposal" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key) === "proposal_result"
.
String
Grant from "distribution" Module Account
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value) === "{distribution module account}"
where
.result.end_block_events[event_index].type === "transfer" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key) === "sender"
.
String
Recipient Account
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value)
where
.result.end_block_events[event_index].type === "transfer" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key === "recipient")
.
String
Grants Amount
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value)
where
.result.end_block_events[event_index].type === "transfer" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key === "amount")
.
Example of Block Results API when Community Pool Spend Proposal Funds is Released:
2. MsgDeposit
Descriptions: Submit a deposit to an existing proposal
Deposit will transfer from the proposer account to the "gov" module account.
Protobuf
Example
Cosmos Transaction Query API: https://rpc.mainnet.crypto.org/cosmos/tx/v1beta1/txs/9CCC988616344C804E8831B6FC6BECD6FD0F815E4E3FF13BDE6B7F8360BF0050
Details
Transaction Type
tx.body.messages[message_index]["@type"] === "/cosmos.gov.v1beta1.MsgDeposit"
String
Deposit From Address
tx.body.messages[message_index].depositor
String
2a. Burn Proposal's Deposit if Proposal does not Get Enough Deposit
If a proposal does not meet the depsoit requirement after the deposit period, the deposit will NOT be returned to the depositors. Those deposits will be burnt from the "gov" module account as well.
The latest deposit requirement ("min_deposit") and deposit period ("max_deposit_period") can be checked on https://rpc.mainnet.crypto.org/cosmos/gov/v1beta1/params/deposit. Note that they are network parameters and may change over time after governance proposals.
To monitor a proposal becomes inactive, it can be detected by monitoring the end_block_events
in Tendermint Block Results API. However, for the amount of deposit burnt, you have to keep track of the deposits made to the proposal before. Note that this operation does not involve any user account as the deposits are burnt.
Tendermint Block Results API: https://rpc.mainnet.crypto.org/block_results?height=195346
Details
Proposal Id
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value) === "{gov module account}"
where
.result.end_block_events[event_index].type === "inactive_proposal" && .result.Base64Decode(end_block_events[event_index].attributes[attribute_index].key) === "proposal_id"
.
String
Assert Proposal is Dropped
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value === "proposal_dropped")
where
.result.end_block_events[event_index].type === "inactive_proposal" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key === "proposal_result"
).
String
2b. Return Proposal's Deposit
There are a few cases where a proposal deposit will be returned to the depositors. For details, please refer to Proposal Result.
The return deposit can be detected by monitoring the end_block_events
in Tendermint Block Results API.
Example
Tendermint Block Results API: https://rpc.mainnet.crypto.org:443/block_results?height=496620
Details
Return From "gov" Module Account
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value) === "{gov module account}"
where
.result.end_block_events[event_index].type === "transfer" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key) === "sender"
.
String
Return To Address
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value)
where
.result.end_block_events[event_index].type === "transfer" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key) === "recipient"
.
String
Returned Deposit Amount
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value)
where
.result.end_block_events[event_index].type === "transfer" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key === "amount"
).
Note that there may be multiple depositors of a proposal, so the event may appear multiple times.
2c. Burn Proposal's Deposit
There are a few cases where proposal deposits will be burnt. For details, please refer to Proposal Result for more details.
If a proposal does not get enough votes that exceed the "quorum" or has the "No with Veto" votes exceed the "veto_threshold", the deposit will NOT be returned to the depositors. Those deposits will be burnt from the "gov" module account as well.
To monitor a proposal that got rejected and deposits got burned, it can be detected by monitoring the end_block_events
Tendermint Block Results API. There will be a "proposal_result" event marking the proposal as rejected, and different from Return Proposal's Deposit, there will be NO transfer event in the end_block_results
, which means the deposit is NOT returned and is burnt.
However, for the amount of deposit burnt, you have to keep track of the deposits made to the proposal before. Note that this operation does not involve any user account as the deposits are burnt.
Details and Example
Proposal Id
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value) === "{gov module account}"
where
.result.end_block_events[event_index].type === "active_proposal" && .result.Base64Decode(end_block_events[event_index].attributes[attribute_index].key) === "proposal_id"
.
String
Assert Proposal is Rejected
Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].value === "proposal_rejected")
where
.result.end_block_events[event_index].type === "active_proposal" && Base64Decode(.result.end_block_events[event_index].attributes[attribute_index].key === "proposal_result"
).
String
Tendermint Block Results API JSON Example (Base64 Decoded):
3. MsgVote
Descriptions: : Submit a vote to an existing proposal
Funds movement: No (Pay for fee only)
4. Proposal Result
Latest tally params can be retrieved from: https://rpc.mainnet.crypto.org/cosmos/gov/v1beta1/params/tallying. The params may change from time to time after the governance proposal.
All voter has no staked coins
Rejects
No
Not enough tally_params.quorum
of votes
Rejects
Yes
No one votes (Everyone abstain)
Rejects
No
More than tally_params.veto_threshold
voter veto
Rejects
Yes
More than tally_params.threshold
non-abstaining votes No
Rejects
No
More than tally_params.threshold
non-abstaining votes Yes
Passes
No
More than tally_params.threshold
non-abstaining votes Yes but the proposal cannot be executed (e.g. Insufficient funds in community pool to spend)
Failed
No
Appendix: Module Accounts on Mainnet
fee_collector
distribution
bonded_tokens_pool
not_bonded_tokens_pool
Last updated