Gov

The Gov Contract contains logic for holding polls and Mirror Token (MIR) staking, and allows the Mirror Protocol to be governed by its users in a decentralized manner. After the initial bootstrapping of Mirror Protocol contracts, the Gov Contract is assigned to be the owner of itself and Mirror Factory.

New proposals for change are submitted as polls, and are voted on by MIR stakers through the voting procedure. Polls can contain messages that can be executed directly without changing the Mirror Protocol code.

The Gov Contract keeps a balance of MIR tokens, which it uses to reward stakers with funds it receives from trading fees sent by the Mirror Collector and user deposits from creating new governance polls. This balance is separate from the Community Pool, which is held by the Community contract (owned by the Gov contract).

Config

Name

Type

Description

mirror_token

HumanAddr

Contract address of Mirror Token (MIR)

quorum

Decimal

Minimum percentage of participation required for a poll to pass

threshold

Decimal

Minimum percentage of yes votes required for a poll to pass

voting_period

u64

Number of blocks during which votes can be cast

proposal_deposit

Uint128

Minimum MIR deposit required for a new poll to be submitted

effective_delay

u64

Number of blocks after a poll passes to apply changes

expiration_period

u64

Number of blocks after a poll's voting period during which the poll can be executed.

InitMsg

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InitMsg {
pub mirror_token: HumanAddr,
pub quorum: Decimal,
pub threshold: Decimal,
pub voting_period: u64,
pub proposal_deposit: Uint128,
pub effective_delay: u64
}
JSON
{
"mirror_token": "terra1...",
"quorum": "0.4",
"threshold": "0.5",
"voting_period": 8,
"proposal_deposit": "1000000"
"effective_delay": 8
}

Key

Type

Description

mirror_token

HumanAddr

Contract address of Mirror Token (MIR)

quorum

Decimal

Minimum percentage of participation required for a poll to pass

threshold

Decimal

Minimum percentage of yes votes required for a poll to pass

voting_period

u64

Number of blocks during which votes can be cast

proposal_deposit

Uint128

Minimum MIR deposit required for a new poll to be submitted

effective_delay

u64

Number of blocks after a poll passes to apply changes

HandleMsg

Receive

Can be called during a CW20 token transfer when the Mint contract is the recipient. Allows the token transfer to execute a Receive Hook as a subsequent action within the same transaction.

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
Receive {
amount: Uint128,
sender: HumanAddr,
msg: Option<Binary>,
}
}
JSON
{
"receive": {
"amount": "10000000",
"sender": "terra1...",
"msg": "eyAiZXhlY3V0ZV9tc2ciOiAiYmxhaCBibGFoIiB9"
}
}

Key

Type

Description

amount

Uint128

Amount of tokens received

sender

HumanAddr

Sender of token transfer

msg*

Binary

Base64-encoded JSON of Receive Hook

* = optional

UpdateConfig

Updates the configuration for the Gov contract.

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
UpdateConfig {
effective_delay: Option<u64>,
owner: Option<HumanAddr>,
proposal_deposit: Option<Uint128>,
quorum: Option<Decimal>,
threshold: Option<Decimal>,
voting_period: Option<u64>,
expiration_period: Option<u64>,
}
}
JSON
{
"update_config": {
"effective_delay": 8,
"owner": "terra1...",
"proposal_deposit": "10000000",
"quorum": "123.456789",
"threshold": "123.456789",
"voting_period": 8,
"expiration_period": 8
}
}

Key

Type

Description

effective_delay*

u64

Number of blocks after a poll passes to apply changes

owner*

HumanAddr

Address of owner of governance contract

proposal_deposit*

Uint128

Minimum deposited MIR tokens for a poll to enter voting

quorum*

Decimal

Percentage of participation (of total staked MIR) required for a poll to pass

threshold*

Decimal

Percentage of yes votes needed for a poll to pass

voting_period*

u64

Number of blocks during which votes for a poll can be cast after it has finished its deposit

expiration_period*

u64

Number of blocks after a poll's voting period during which the poll can be executed.

* = optional

CastVote

Submits a user's vote for an active poll. Once a user has voted, they cannot change their vote with subsequent messages (increasing voting power, changing vote option, cancelling vote, etc.)

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
CastVote {
amount: Uint128,
poll_id: u64,
vote: VoteOption,
}
}
JSON
{
"cast_vote": {
"amount": "10000000",
"poll_id": 8,
"vote": "yes/no"
}
}

Key

Type

Description

amount

Uint128

Amount of voting power (staked MIR) to allocate

poll_id

u64

Poll ID

vote

VoteOption

Can be yes or no

WithdrawVotingTokens

Removes deposited MIR tokens from a staking position and returns them to a user's balance.

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
WithdrawVotingTokens {
amount: Option<Uint128>,
}
}
JSON
{
"withdraw_voting_tokens": {
"amount": "10000000"
}
}

Key

Type

Description

amount*

Uint128

Amount of MIR tokens to withdraw. If empty, all staked MIR tokens are withdrawn.

* = optional

EndPoll

Can be issued by anyone to end the voting for an active poll. Triggers tally the results to determine whether the poll has passed. The current block height must exceed the end height of voting phase.

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
EndPoll {
poll_id: u64,
}
}
JSON
{
"end_poll": {
"poll_id": 8
}
}

Key

Type

Description

poll_id

u64

Poll ID

ExecutePoll

Can be issued by anyone to implement into action the contents of a passed poll. The current block height must exceed the end height of the poll's effective delay.

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
ExecutePoll {
poll_id: u64,
}
}
JSON
{
"execute_poll": {
"poll_id": 8
}
}

Key

Type

Description

poll_id

u64

Poll ID

Receive Hooks

StakeVotingTokens

WARNING

If you send MIR tokens to the Gov contract without issuing this hook, they will not be staked and will be irrevocably donated to the reward pool for stakers.

Issued when sending MIR tokens to the Gov contract to add them to their MIR staking position.

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Cw20HookMsg {
StakeVotingTokens {}
}
JSON
{
"stake_voting_tokens": {}
}

CreatePoll

Issued when sending MIR tokens to the Gov contract to create a new poll. Will only succeed if the amount of tokens sent meets the configured proposal_deposit amount. Contains a generic message to be issued by the Gov contract if it passes (can invoke messages in other contracts it owns).

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Cw20HookMsg {
CreatePoll {
description: String,
execute_msg: Option<ExecuteMsg>,
link: Option<String>,
title: String,
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub struct ExecuteMsg {
pub contract: HumanAddr,
pub msg: Binary,
}
JSON
{
"create_poll": {
"description": "...",
"execute_msg": {
"contract": "terra1...",
"msg": "eyAiZXhlY3V0ZV9tc2ciOiAiYmxhaCBibGFoIiB9"
},
"link": "...",
"title": "..."
}
}

Key

Type

Description

description

string

Poll description

execute_msg*

ExecuteMsg

Message to be executed by Gov contract

link*

string

URL to external post about poll (forum, PDF, etc.)

title

string

Poll title

* = optional

QueryMsg

Config

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
Config {}
}
JSON
{
"config": {}
}

Key

Type

Description

State

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
State {}
}
JSON
{
"state": {}
}

Key

Type

Description

Staker

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
Staker {
address: HumanAddr,
}
}
JSON
{
"staker": {
"address": "terra1..."
}
}

Key

Type

Description

address

HumanAddr

Address of staker

Poll

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
Poll {
poll_id: u64,
}
}
JSON
{
"poll": {
"poll_id": 8
}
}

Key

Type

Description

poll_id

u64

Poll ID

Polls

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
Polls {
filter: Option<PollStatus>,
limit: Option<u32>,
start_after: Option<u64>,
}
}
JSON
{
"polls": {
"filter": "in_progress",
"limit": 8,
"start_after": 8
}
}

Key

Type

Description

filter*

PollStatus

Can be yes or no

limit*

u32

Limit of results to fetch

start_after*

u64

Begins search query at specific ID

* = optional

Voters

Rust
JSON
Rust
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum QueryMsg {
Voters {
limit: Option<u32>,
poll_id: u64,
start_after: Option<HumanAddr>,
}
}
JSON
{
"voters": {
"limit": 8,
"poll_id": 8,
"start_after": "terra1..."
}
}

Key

Type

Description

limit*

u32

Limit of results to fetch

poll_id

u64

Poll ID

start_after*

HumanAddr

Begins search query with prefix

* = optional