MultiTestGovernance

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);