abstract_sdk/cw_helpers/
cw_ownable.rs

1/// Macro to update the ownership of an Abstract contract.
2///
3/// ```rustignore
4/// pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> ContractResult {
5///     match msg {
6///         ...
7///         ExecuteMsg::UpdateOwnership(action) => {
8///             execute_update_ownership!(ContractResponse, deps, env, info, action)
9///         }
10///     }
11/// }
12/// ```
13#[macro_export]
14macro_rules! execute_update_ownership {
15    ($response_type:ident, $deps:expr, $env:expr, $info:expr, $action:expr) => {{
16        let ownership = cw_ownable::update_ownership($deps, &$env.block, &$info.sender, $action)?;
17        Ok($response_type::new(
18            "update_ownership",
19            ownership.into_attributes(),
20        ))
21    }};
22}
23
24/// Macro to query the ownership of a contract.
25///
26/// ```rustignore
27/// pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
28///     match msg {
29///         ...
30///         QueryMsg::Ownership {} => query_ownership!(deps),
31///     }
32/// }
33/// ```
34#[macro_export]
35macro_rules! query_ownership {
36    ($deps:expr) => {{
37        cosmwasm_std::to_json_binary(&cw_ownable::get_ownership($deps.storage)?)
38    }};
39}
40
41#[cfg(test)]
42mod tests {
43    use abstract_macros::abstract_response;
44    use abstract_testing::mock_env_validated;
45    use cosmwasm_schema::{cw_serde, QueryResponses};
46    use cosmwasm_std::{
47        from_json,
48        testing::{message_info, mock_dependencies},
49        Addr, Binary, StdError, StdResult,
50    };
51    use cw_ownable::{cw_ownable_execute, cw_ownable_query, Action, OwnershipError};
52    use thiserror::Error;
53
54    const MOCK_CONTRACT: &str = "contract";
55
56    #[abstract_response(MOCK_CONTRACT)]
57    pub struct MockResponse;
58
59    #[cw_ownable_execute]
60    #[cw_serde]
61    enum ExecuteMsg {}
62
63    #[cw_ownable_query]
64    #[cw_serde]
65    #[derive(QueryResponses)]
66    enum QueryMsg {}
67
68    #[derive(Error, Debug, PartialEq)]
69    pub enum MockError {
70        #[error(transparent)]
71        Std(#[from] StdError),
72        #[error(transparent)]
73        Ownership(#[from] cw_ownable::OwnershipError),
74    }
75
76    const NEW_OWNER: &str = "new_owner";
77    const OLD_OWNER: &str = "old_owner";
78
79    #[coverage_helper::test]
80    fn test_update_ownership_macro() -> Result<(), MockError> {
81        let mut deps = mock_dependencies();
82
83        let env = mock_env_validated(deps.api);
84        let old_owner = deps.api.addr_make(OLD_OWNER);
85        let new_owner = deps.api.addr_make(NEW_OWNER);
86        let info = message_info(&old_owner, &[]);
87
88        cw_ownable::initialize_owner(&mut deps.storage, &deps.api, Some(old_owner.as_str()))?;
89
90        let mut_deps = deps.as_mut();
91
92        // ExecuteMsg for testing the macro
93        let transfer_ownership_action = Action::TransferOwnership {
94            new_owner: new_owner.to_string(),
95            expiry: None,
96        };
97
98        let ownership_msg = ExecuteMsg::UpdateOwnership(transfer_ownership_action);
99
100        let result: Result<_, OwnershipError> = match ownership_msg {
101            ExecuteMsg::UpdateOwnership(action) => {
102                execute_update_ownership!(MockResponse, mut_deps, env, info, action)
103            }
104        };
105
106        let expected_response = MockResponse::new(
107            "update_ownership",
108            vec![
109                ("owner", old_owner.as_str()),
110                ("pending_owner", new_owner.as_str()),
111                ("pending_expiry", "none"),
112            ],
113        );
114
115        assert_eq!(result.unwrap(), expected_response);
116
117        Ok(())
118    }
119
120    #[coverage_helper::test]
121    fn test_query_ownership_macro() -> Result<(), MockError> {
122        let mut deps = mock_dependencies();
123        let _env = mock_env_validated(deps.api);
124
125        let old_owner = deps.api.addr_make("owner1");
126
127        cw_ownable::initialize_owner(&mut deps.storage, &deps.api, Some(old_owner.as_str()))?;
128
129        // Ownership query message for testing the macro
130        let ownership_query_msg = QueryMsg::Ownership {};
131
132        let result: StdResult<Binary> = match ownership_query_msg {
133            QueryMsg::Ownership {} => query_ownership!(deps.as_ref()),
134        };
135
136        let expected = cw_ownable::Ownership {
137            owner: Some(old_owner),
138            pending_owner: None,
139            pending_expiry: None,
140        };
141
142        // Deserialize the query response
143        let actual: cw_ownable::Ownership<Addr> = from_json(result.unwrap())?;
144
145        assert_eq!(actual, expected);
146
147        Ok(())
148    }
149}