Skip to content

Commit

Permalink
Merge pull request #8 from confio/6-voting-contract-tests
Browse files Browse the repository at this point in the history
voting-contract: tests
  • Loading branch information
maurolacy committed Jan 13, 2022
2 parents 02296ed + ffb13d6 commit cad4bf4
Show file tree
Hide file tree
Showing 19 changed files with 1,825 additions and 54 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 7 additions & 12 deletions contracts/tgrade-community-pool/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ use cosmwasm_std::entry_point;
use cosmwasm_std::{to_binary, BankMsg, Binary, Coin, Deps, DepsMut, Env, MessageInfo, StdResult};

use cw2::set_contract_version;
use cw3::Status;
use tg_bindings::TgradeMsg;

use crate::msg::{ExecuteMsg, InstantiateMsg, Proposal, QueryMsg};
use crate::ContractError;

use tg_voting_contract::state::{proposals, CONFIG as VOTING_CONFIG};
use tg_voting_contract::state::CONFIG as VOTING_CONFIG;
use tg_voting_contract::{
close as execute_close, list_proposals, list_voters, list_votes, propose, query_group_contract,
query_proposal, query_rules, query_vote, query_voter, reverse_proposals, vote as execute_vote,
close as execute_close, list_proposals, list_voters, list_votes, mark_executed, propose,
query_group_contract, query_proposal, query_rules, query_vote, query_voter, reverse_proposals,
vote as execute_vote,
};

pub type Response = cosmwasm_std::Response<TgradeMsg>;
Expand Down Expand Up @@ -50,7 +50,7 @@ pub fn execute(
execute_vote::<Proposal>(deps, env, info, proposal_id, vote)
.map_err(ContractError::from)
}
ExecuteMsg::Execute { proposal_id } => execute_execute(deps, info, proposal_id),
ExecuteMsg::Execute { proposal_id } => execute_execute(deps, env, info, proposal_id),
ExecuteMsg::Close { proposal_id } => {
execute_close::<Proposal>(deps, env, info, proposal_id).map_err(ContractError::from)
}
Expand Down Expand Up @@ -97,19 +97,14 @@ pub fn execute_send_proposal(to_address: String, amount: Coin) -> Result<Respons

pub fn execute_execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
proposal_id: u64,
) -> Result<Response, ContractError> {
use Proposal::*;

// anyone can trigger this if the vote passed
let prop = proposals::<Proposal>().load(deps.storage, proposal_id)?;

// we allow execution even after the proposal "expiration" as long as all vote come in before
// that point. If it was approved on time, it can be executed any time.
if prop.status != Status::Passed {
return Err(ContractError::WrongExecuteStatus {});
}
let prop = mark_executed::<Proposal>(deps, env, proposal_id)?;

// dispatch all proposed messages
let resp = match prop.proposal {
Expand Down
3 changes: 0 additions & 3 deletions contracts/tgrade-community-pool/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ pub enum ContractError {

#[error("{0}")]
Voting(tg_voting_contract::ContractError),

#[error("Proposal must have passed and not yet been executed")]
WrongExecuteStatus {},
}

impl From<tg_voting_contract::ContractError> for ContractError {
Expand Down
58 changes: 23 additions & 35 deletions contracts/tgrade-validator-voting/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use cosmwasm_std::{
};

use cw2::set_contract_version;
use cw3::Status;
use tg_bindings::{
request_privileges, BlockParams, ConsensusParams, EvidenceParams, GovProposal, Privilege,
PrivilegeChangeMsg, TgradeMsg, TgradeSudoMsg,
Expand All @@ -15,11 +14,10 @@ use tg_bindings::{
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg, ValidatorProposal};
use crate::ContractError;

use tg_voting_contract::state::proposals;
use tg_voting_contract::{
close as execute_close, list_proposals, list_voters, list_votes, propose as execute_propose,
query_group_contract, query_proposal, query_rules, query_vote, query_voter, reverse_proposals,
vote as execute_vote,
close as execute_close, list_proposals, list_voters, list_votes, mark_executed,
propose as execute_propose, query_group_contract, query_proposal, query_rules, query_vote,
query_voter, reverse_proposals, vote as execute_vote,
};

pub type Response = cosmwasm_std::Response<TgradeMsg>;
Expand Down Expand Up @@ -67,7 +65,7 @@ pub fn execute(
execute_vote::<ValidatorProposal>(deps, env, info, proposal_id, vote)
.map_err(ContractError::from)
}
Execute { proposal_id } => execute_execute(deps, info, proposal_id),
Execute { proposal_id } => execute_execute(deps, env, info, proposal_id),
Close { proposal_id } => execute_close::<ValidatorProposal>(deps, env, info, proposal_id)
.map_err(ContractError::from),
}
Expand Down Expand Up @@ -108,40 +106,33 @@ fn confirm_admin_in_contract(

pub fn execute_execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
proposal_id: u64,
) -> Result<Response, ContractError> {
use ValidatorProposal::*;
// anyone can trigger this if the vote passed
let proposal = mark_executed::<ValidatorProposal>(deps, env, proposal_id)?;

let mut proposal = proposals::<ValidatorProposal>().load(deps.storage, proposal_id)?;

// we allow execution even after the proposal "expiration" as long as all vote come in before
// that point. If it was approved on time, it can be executed any time.
if proposal.status != Status::Passed {
return Err(ContractError::WrongExecuteStatus {});
}

let prop = proposal.clone();
let msg = match prop.proposal {
let msg = match proposal.proposal {
RegisterUpgrade { name, height, info } => SubMsg::new(TgradeMsg::ExecuteGovProposal {
title: prop.title,
description: prop.description,
title: proposal.title,
description: proposal.description,
proposal: GovProposal::RegisterUpgrade { name, height, info },
}),
CancelUpgrade {} => SubMsg::new(TgradeMsg::ExecuteGovProposal {
title: prop.title,
description: prop.description,
title: proposal.title,
description: proposal.description,
proposal: GovProposal::CancelUpgrade {},
}),
PinCodes(code_ids) => SubMsg::new(TgradeMsg::ExecuteGovProposal {
title: prop.title,
description: prop.description,
title: proposal.title,
description: proposal.description,
proposal: GovProposal::PinCodes { code_ids },
}),
UnpinCodes(code_ids) => SubMsg::new(TgradeMsg::ExecuteGovProposal {
title: prop.title,
description: prop.description,
title: proposal.title,
description: proposal.description,
proposal: GovProposal::UnpinCodes { code_ids },
}),
UpdateConsensusBlockParams { max_bytes, max_gas } => {
Expand Down Expand Up @@ -173,10 +164,6 @@ pub fn execute_execute(
}),
};

// set it to executed
proposal.status = Status::Executed;
proposals::<ValidatorProposal>().save(deps.storage, proposal_id, &proposal)?;

Ok(Response::new()
.add_attribute("action", "execute")
.add_attribute("sender", info.sender)
Expand Down Expand Up @@ -262,9 +249,10 @@ mod tests {
Addr, CosmosMsg, Decimal, SubMsg,
};
use tg_utils::Expiration;
use tg_voting_contract::state::{Proposal, Votes, VotingRules};
use tg_voting_contract::state::{proposals, Proposal, Votes, VotingRules};

use super::*;
use cw3::Status;

#[derive(serde::Serialize)]
struct DummyMigrateMsg {}
Expand Down Expand Up @@ -306,7 +294,7 @@ mod tests {
)
.unwrap();

let res = execute_execute(deps.as_mut(), mock_info("sender", &[]), 1).unwrap();
let res = execute_execute(deps.as_mut(), env, mock_info("sender", &[]), 1).unwrap();
assert_eq!(
res.messages,
vec![SubMsg::new(WasmMsg::Migrate {
Expand Down Expand Up @@ -349,7 +337,7 @@ mod tests {
)
.unwrap();

let res = execute_execute(deps.as_mut(), mock_info("sender", &[]), 1).unwrap();
let res = execute_execute(deps.as_mut(), env, mock_info("sender", &[]), 1).unwrap();
assert_eq!(
res.messages,
vec![SubMsg::new(CosmosMsg::Custom(
Expand Down Expand Up @@ -394,7 +382,7 @@ mod tests {
)
.unwrap();

let res = execute_execute(deps.as_mut(), mock_info("sender", &[]), 1).unwrap();
let res = execute_execute(deps.as_mut(), env, mock_info("sender", &[]), 1).unwrap();
assert_eq!(
res.messages,
vec![SubMsg::new(CosmosMsg::Custom(
Expand Down Expand Up @@ -439,7 +427,7 @@ mod tests {
)
.unwrap();

let res = execute_execute(deps.as_mut(), mock_info("sender", &[]), 1).unwrap();
let res = execute_execute(deps.as_mut(), env, mock_info("sender", &[]), 1).unwrap();
assert_eq!(
res.messages,
vec![SubMsg::new(CosmosMsg::Custom(
Expand Down Expand Up @@ -487,7 +475,7 @@ mod tests {
)
.unwrap();

let res = execute_execute(deps.as_mut(), mock_info("sender", &[]), 1).unwrap();
let res = execute_execute(deps.as_mut(), env, mock_info("sender", &[]), 1).unwrap();
assert_eq!(
res.messages,
vec![SubMsg::new(CosmosMsg::Custom(TgradeMsg::ConsensusParams(
Expand Down Expand Up @@ -538,7 +526,7 @@ mod tests {
)
.unwrap();

let res = execute_execute(deps.as_mut(), mock_info("sender", &[]), 1).unwrap();
let res = execute_execute(deps.as_mut(), env, mock_info("sender", &[]), 1).unwrap();
assert_eq!(
res.messages,
vec![SubMsg::new(CosmosMsg::Custom(TgradeMsg::ConsensusParams(
Expand Down
3 changes: 0 additions & 3 deletions contracts/tgrade-validator-voting/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ pub enum ContractError {
#[error("Received system callback we didn't expect")]
UnsupportedSudoType {},

#[error("Proposal must have passed and not yet been executed")]
WrongExecuteStatus {},

#[error("Unauthorized: {0}")]
Unauthorized(String),
}
Expand Down
7 changes: 6 additions & 1 deletion packages/voting-contract/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ tg-utils = { version = "0.5.2", path = "../utils" }
thiserror = { version = "1" }

[dev-dependencies]
cosmwasm-schema = { version = "1.0.0-beta" }
anyhow = "1"
cosmwasm-schema = "1.0.0-beta"
cw-multi-test = "0.11.0"
derivative = "2"
tg-bindings-test = { path = "../../packages/bindings-test", version = "0.5.2" }
tg4-engagement = { path = "../../contracts/tg4-engagement", version = "0.5.2", features = ["library"] }
3 changes: 3 additions & 0 deletions packages/voting-contract/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,7 @@ pub enum ContractError {

#[error("Cannot close completed or passed proposals")]
WrongCloseStatus {},

#[error("Proposal must have passed and not yet been executed")]
WrongExecuteStatus {},
}
28 changes: 28 additions & 0 deletions packages/voting-contract/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod error;
pub mod msg;
#[cfg(test)]
mod multitest;
pub mod state;

pub use error::ContractError;
Expand Down Expand Up @@ -148,6 +150,32 @@ where
.add_attribute("status", format!("{:?}", prop.status)))
}

/// Checks if a given proposal is passed and can then be executed, and returns it.
/// Notice that this call is mutable, so, better execute the returned proposal after this succeeds,
/// as you you wouldn't be able to execute it in the future (If the contract call errors, this status
/// change will be reverted / ignored).
pub fn mark_executed<P>(
deps: DepsMut,
env: Env,
proposal_id: u64,
) -> Result<Proposal<P>, ContractError>
where
P: Serialize + DeserializeOwned,
{
let mut proposal = proposals::<P>().load(deps.storage, proposal_id)?;

// We allow execution even after the proposal "expiration" as long as all votes come in before
// that point. If it was approved on time, it can be executed any time.
if proposal.current_status(&env.block) != Status::Passed {
return Err(ContractError::WrongExecuteStatus {});
}

// Set it to executed
proposal.status = Status::Executed;
proposals::<P>().save(deps.storage, proposal_id, &proposal)?;
Ok(proposal)
}

pub fn close<P>(
deps: DepsMut,
env: Env,
Expand Down
15 changes: 15 additions & 0 deletions packages/voting-contract/src/multitest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use suite::SuiteBuilder;

mod closing;
mod contracts;
mod early_end;
mod group_change;
mod proposing;
mod queries;
mod suite;
mod voting;

#[test]
fn simple_instantiate() {
SuiteBuilder::new().build();
}
Loading

0 comments on commit cad4bf4

Please sign in to comment.