Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added message to reset approver back to DAO #774

Merged
merged 3 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
],
"properties": {
"msg": {
"$ref": "#/definitions/Empty"
"$ref": "#/definitions/ExecuteExt"
}
},
"additionalProperties": false
Expand Down Expand Up @@ -298,9 +298,22 @@
}
]
},
"Empty": {
"description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)",
"type": "object"
"ExecuteExt": {
"oneOf": [
{
"type": "object",
"required": [
"reset_approver"
],
"properties": {
"reset_approver": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
}
]
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
Expand Down
45 changes: 43 additions & 2 deletions contracts/pre-propose/dao-pre-propose-approver/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use dao_pre_propose_base::{error::PreProposeError, state::PreProposeContract};
use dao_voting::status::Status;

use crate::msg::{
BaseInstantiateMsg, ExecuteMsg, InstantiateMsg, ProposeMessageInternal, QueryExt, QueryMsg,
BaseInstantiateMsg, ExecuteExt, ExecuteMsg, InstantiateMsg, ProposeMessageInternal, QueryExt,
QueryMsg,
};
use crate::state::{
PRE_PROPOSE_APPROVAL_CONTRACT, PRE_PROPOSE_ID_TO_PROPOSAL_ID, PROPOSAL_ID_TO_PRE_PROPOSE_ID,
Expand All @@ -23,7 +24,7 @@ use crate::state::{
pub(crate) const CONTRACT_NAME: &str = "crates.io:dao-pre-propose-approver";
pub(crate) const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

type PrePropose = PreProposeContract<Empty, Empty, QueryExt, ApproverProposeMessage>;
type PrePropose = PreProposeContract<Empty, ExecuteExt, QueryExt, ApproverProposeMessage>;

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
Expand Down Expand Up @@ -88,6 +89,9 @@ pub fn execute(
proposal_id,
new_status,
} => execute_proposal_completed(deps, info, proposal_id, new_status),
ExecuteMsg::Extension { msg } => match msg {
ExecuteExt::ResetApprover {} => execute_reset_approver(deps, env, info),
},
_ => PrePropose::default().execute(deps, env, info, msg),
}
}
Expand Down Expand Up @@ -184,6 +188,43 @@ pub fn execute_proposal_completed(
}
}

pub fn execute_reset_approver(
deps: DepsMut,
env: Env,
info: MessageInfo,
) -> Result<Response, PreProposeError> {
// Check that this is coming from the DAO.
let dao = PrePropose::default().dao.load(deps.storage)?;
if info.sender != dao {
return Err(PreProposeError::Unauthorized {});
}

let pre_propose_approval_contract = PRE_PROPOSE_APPROVAL_CONTRACT.load(deps.storage)?;

let reset_messages = vec![
// Remove the proposal submitted hook.
CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: pre_propose_approval_contract.to_string(),
msg: to_json_binary(&PreProposeApprovalExecuteMsg::RemoveProposalSubmittedHook {
address: env.contract.address.to_string(),
})?,
funds: vec![],
}),
// Set pre-propose-approval approver to the DAO.
CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: pre_propose_approval_contract.to_string(),
msg: to_json_binary(&PreProposeApprovalExecuteMsg::Extension {
msg: ApprovalExt::UpdateApprover {
address: dao.to_string(),
},
})?,
funds: vec![],
}),
];

Ok(Response::default().add_messages(reset_messages))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
Expand Down
9 changes: 8 additions & 1 deletion contracts/pre-propose/dao-pre-propose-approver/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ pub struct InstantiateMsg {
pub pre_propose_approval_contract: String,
}

#[cw_serde]
pub enum ExecuteExt {
// Reset approver back to DAO that set up this approver contract. Only
// callable by the DAO.
NoahSaso marked this conversation as resolved.
Show resolved Hide resolved
ResetApprover {},
}

#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryExt {
Expand All @@ -22,7 +29,7 @@ pub enum QueryExt {
}

pub type BaseInstantiateMsg = InstantiateBase<Empty>;
pub type ExecuteMsg = ExecuteBase<ApproverProposeMessage, Empty>;
pub type ExecuteMsg = ExecuteBase<ApproverProposeMessage, ExecuteExt>;
pub type QueryMsg = QueryBase<QueryExt>;

/// Internal version of the propose message that includes the
Expand Down
127 changes: 112 additions & 15 deletions contracts/pre-propose/dao-pre-propose-approver/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ use dao_voting::{

use crate::contract::{CONTRACT_NAME, CONTRACT_VERSION};
use crate::msg::InstantiateMsg as ApproverInstantiateMsg;
use crate::msg::{QueryExt as ApproverQueryExt, QueryMsg as ApproverQueryMsg};
use crate::msg::{
ExecuteExt as ApproverExecuteExt, ExecuteMsg as ApproverExecuteMsg,
QueryExt as ApproverQueryExt, QueryMsg as ApproverQueryMsg,
};

// The approver dao contract is the 6th contract instantiated
const APPROVER: &str = "contract6";
Expand Down Expand Up @@ -166,7 +169,7 @@ struct DefaultTestSetup {
core_addr: Addr,
proposal_single: Addr,
pre_propose: Addr,
_approver_core_addr: Addr,
approver_core_addr: Addr,
pre_propose_approver: Addr,
proposal_single_approver: Addr,
}
Expand Down Expand Up @@ -238,7 +241,7 @@ fn setup_default_test(
pre_propose.to_string(),
);

let _approver_core_addr = instantiate_with_cw4_groups_governance(
let approver_core_addr = instantiate_with_cw4_groups_governance(
app,
dps_id,
to_json_binary(&proposal_module_instantiate).unwrap(),
Expand All @@ -256,7 +259,7 @@ fn setup_default_test(
let proposal_modules: Vec<ProposalModule> = app
.wrap()
.query_wasm_smart(
_approver_core_addr.clone(),
approver_core_addr.clone(),
&dao_interface::msg::QueryMsg::ProposalModules {
start_after: None,
limit: None,
Expand All @@ -283,15 +286,15 @@ fn setup_default_test(
get_proposal_module(app, pre_propose_approver.clone())
);
assert_eq!(
_approver_core_addr,
approver_core_addr,
get_dao(app, pre_propose_approver.clone())
);

DefaultTestSetup {
core_addr,
proposal_single,
pre_propose,
_approver_core_addr,
approver_core_addr,
proposal_single_approver,
pre_propose_approver,
}
Expand Down Expand Up @@ -568,7 +571,7 @@ fn test_native_permutation(
core_addr,
proposal_single,
pre_propose,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver,
pre_propose_approver: _,
} = setup_default_test(
Expand Down Expand Up @@ -676,7 +679,7 @@ fn test_cw20_permutation(
core_addr,
proposal_single,
pre_propose,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver,
pre_propose_approver: _,
} = setup_default_test(
Expand Down Expand Up @@ -968,7 +971,7 @@ fn test_multiple_open_proposals() {
core_addr: _,
proposal_single,
pre_propose,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver,
pre_propose_approver: _,
} = setup_default_test(
Expand Down Expand Up @@ -1065,7 +1068,7 @@ fn test_set_version() {
core_addr: _,
proposal_single: _,
pre_propose: _,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver: _,
pre_propose_approver,
} = setup_default_test(
Expand Down Expand Up @@ -1107,7 +1110,7 @@ fn test_permissions() {
core_addr,
proposal_single: _,
pre_propose,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver: _,
pre_propose_approver: _,
} = setup_default_test(
Expand Down Expand Up @@ -1169,7 +1172,7 @@ fn test_approval_and_rejection_permissions() {
core_addr: _,
proposal_single: _,
pre_propose,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver: _,
pre_propose_approver: _,
} = setup_default_test(
Expand Down Expand Up @@ -1235,7 +1238,7 @@ fn test_propose_open_proposal_submission() {
core_addr: _,
proposal_single,
pre_propose,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver,
pre_propose_approver,
} = setup_default_test(
Expand Down Expand Up @@ -1301,7 +1304,7 @@ fn test_update_config() {
core_addr,
proposal_single,
pre_propose,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver,
pre_propose_approver: _,
} = setup_default_test(&mut app, None, false);
Expand Down Expand Up @@ -1418,7 +1421,7 @@ fn test_withdraw() {
core_addr,
proposal_single,
pre_propose,
_approver_core_addr: _,
approver_core_addr: _,
proposal_single_approver,
pre_propose_approver: _,
} = setup_default_test(&mut app, None, false);
Expand Down Expand Up @@ -1571,3 +1574,97 @@ fn test_withdraw() {
let balance = get_balance_native(&app, core_addr.as_str(), "ujuno");
assert_eq!(balance, Uint128::new(30));
}

#[test]
fn test_reset_approver() {
let mut app = App::default();

// Need to instantiate this so contract addresses match with cw20 test cases
let _ = instantiate_cw20_base_default(&mut app);

let DefaultTestSetup {
core_addr: _,
proposal_single: _,
pre_propose,
approver_core_addr,
proposal_single_approver: _,
pre_propose_approver,
} = setup_default_test(
&mut app,
Some(UncheckedDepositInfo {
denom: DepositToken::Token {
denom: UncheckedDenom::Native("ujuno".to_string()),
},
amount: Uint128::new(10),
refund_policy: DepositRefundPolicy::Always,
}),
false,
);

// Ensure approver is set to the pre_propose_approver
let approver: Addr = app
.wrap()
.query_wasm_smart(
pre_propose.clone(),
&QueryMsg::QueryExtension {
msg: QueryExt::Approver {},
},
)
.unwrap();
assert_eq!(approver, pre_propose_approver);

// Fail to change approver by non-approver.
let err: PreProposeError = app
.execute_contract(
Addr::unchecked("someone"),
pre_propose.clone(),
&ExecuteMsg::Extension {
msg: ExecuteExt::UpdateApprover {
address: "someone".to_string(),
},
},
&[],
)
.unwrap_err()
.downcast()
.unwrap();
assert_eq!(err, PreProposeError::Unauthorized {});

// Fail to reset approver back to approver DAO by non-approver.
let err: PreProposeError = app
.execute_contract(
Addr::unchecked("someone"),
pre_propose_approver.clone(),
&ApproverExecuteMsg::Extension {
msg: ApproverExecuteExt::ResetApprover {},
},
&[],
)
.unwrap_err()
.downcast()
.unwrap();
assert_eq!(err, PreProposeError::Unauthorized {});

// Reset approver back to approver DAO.
app.execute_contract(
approver_core_addr.clone(),
pre_propose_approver.clone(),
&ApproverExecuteMsg::Extension {
msg: ApproverExecuteExt::ResetApprover {},
},
&[],
)
.unwrap();

// Ensure approver is reset back to the approver DAO
let approver: Addr = app
.wrap()
.query_wasm_smart(
pre_propose.clone(),
&QueryMsg::QueryExtension {
msg: QueryExt::Approver {},
},
)
.unwrap();
assert_eq!(approver, approver_core_addr);
}
Loading