Skip to main content

Governance

MultiTest provides two minimal implementations of the governance module that do not replicate the real blockchain behavior: GovAcceptingModule and GovFailingModule. The default chain configuration is using GovFailingModule.

The following sections provide examples of how to initialize a specific governance module and how to execute governance messages in tests.

Default governance module​

Currently, in MultiTest, the default governance module is GovFailingModule, and no additional configuration is required to use it.

GovMsg::Vote​

use cosmwasm_std::{GovMsg, VoteOption};
use cw_multi_test::{no_init, AppBuilder, Executor, IntoAddr};

// Build the application with default (always failing) governance module.
let mut app = AppBuilder::default().build(no_init);

// Prepare sender address.
let sender_addr = "sender".into_addr();

// Prepare message for vote.
let vote_msg = GovMsg::Vote {
proposal_id: 1,
option: VoteOption::Yes,
};

// Execute vote governance message.
let response = app.execute(sender_addr, vote_msg.into()).unwrap_err();

// Always an error is returned.
assert!(response.to_string().starts_with("Unexpected exec msg Vote"));

GovMsg::VoteWeighted​

use cosmwasm_std::{Decimal, GovMsg, Uint128, VoteOption, WeightedVoteOption};
use cw_multi_test::{no_init, AppBuilder, Executor, IntoAddr};

// Build the application with default (always failing) governance module.
let mut app = AppBuilder::default().build(no_init);

// Prepare sender address.
let sender_addr = "sender".into_addr();

// Prepare message for weighted vote.
let vote_msg = GovMsg::VoteWeighted {
proposal_id: 1,
options: vec![WeightedVoteOption {
option: VoteOption::Yes,
weight: Decimal::new(Uint128::new(12)),
}],
};

// Execute weighted vote governance message.
let response = app.execute(sender_addr, vote_msg.into()).unwrap_err();

// Always an error is returned.
assert!(response.to_string().starts_with("Unexpected exec msg VoteWeighted"));

Failing governance module​

Executing governance messages using GovFailingModule always returns an error.

GovMsg::Vote​

use cosmwasm_std::{GovMsg, VoteOption};
use cw_multi_test::{no_init, AppBuilder, Executor, GovFailingModule, IntoAddr};

// Build the application with always failing governance module.
let mut app = AppBuilder::default()
.with_gov(GovFailingModule::new())
.build(no_init);

// Prepare sender address.
let sender_addr = "sender".into_addr();

// Prepare message for vote.
let vote_msg = GovMsg::Vote {
proposal_id: 1,
option: VoteOption::Yes,
};

// Execute vote governance message.
let response = app.execute(sender_addr, vote_msg.into()).unwrap_err();

// Always an error is returned.
assert!(response.to_string().starts_with("Unexpected exec msg Vote"));

GovMsg::VoteWeighted​

use cosmwasm_std::{Decimal, GovMsg, Uint128, VoteOption, WeightedVoteOption};
use cw_multi_test::{no_init, AppBuilder, Executor, GovFailingModule, IntoAddr};

// Build the application with always failing governance module.
let mut app = AppBuilder::default()
.with_gov(GovFailingModule::new())
.build(no_init);

// Prepare sender address.
let sender_addr = "sender".into_addr();

// Prepare message for weighted vote.
let vote_msg = GovMsg::VoteWeighted {
proposal_id: 1,
options: vec![WeightedVoteOption {
option: VoteOption::Yes,
weight: Decimal::new(Uint128::new(12)),
}],
};

// Execute weighted vote governance message.
let response = app.execute(sender_addr, vote_msg.into()).unwrap_err();

// Always an error is returned.
assert!(response.to_string().starts_with("Unexpected exec msg VoteWeighted"));

Accepting governance module​

Executing governance messages using GovAcceptingModule always succeeds, but the returned data is empty.

GovMsg::Vote​

use cosmwasm_std::{GovMsg, VoteOption};
use cw_multi_test::{no_init, AppBuilder, Executor, GovAcceptingModule, IntoAddr};

// Build the application with always failing governance module.
let mut app = AppBuilder::default()
.with_gov(GovAcceptingModule::new())
.build(no_init);

// Prepare sender address.
let sender_addr = "sender".into_addr();

// Prepare message for vote.
let vote_msg = GovMsg::Vote {
proposal_id: 1,
option: VoteOption::Yes,
};

// Execute vote governance message.
let response = app.execute(sender_addr, vote_msg.into()).unwrap();

// Always empty data is returned.
assert_eq!(None, response.data);

GovMsg::VoteWeighted​

use cosmwasm_std::{Decimal, GovMsg, Uint128, VoteOption, WeightedVoteOption};
use cw_multi_test::{no_init, AppBuilder, Executor, GovAcceptingModule, IntoAddr};

// Build the application with always failing governance module.
let mut app = AppBuilder::default()
.with_gov(GovAcceptingModule::new())
.build(no_init);

// Prepare sender address.
let sender_addr = "sender".into_addr();

// Prepare message for weighted vote.
let vote_msg = GovMsg::VoteWeighted {
proposal_id: 1,
options: vec![WeightedVoteOption {
option: VoteOption::Yes,
weight: Decimal::new(Uint128::new(12)),
}],
};

// Execute weighted vote governance message.
let response = app.execute(sender_addr, vote_msg.into()).unwrap();

// Always empty data is returned.
assert_eq!(None, response.data);