bvs_pauser/
lib.rs

1pub mod contract;
2pub mod msg;
3pub mod testing;
4
5mod error;
6mod state;
7
8pub use crate::error::PauserError;
9
10#[cfg(feature = "library")]
11pub mod api {
12    use crate::msg::{CanExecuteFlag, CanExecuteResponse, QueryMsg};
13    use cosmwasm_std::{Addr, Deps, Env, MessageInfo, StdError, StdResult, Storage};
14    use cw_storage_plus::Item;
15
16    pub use strum::Display;
17
18    /// Errors associated with the BVS Pauser.
19    #[derive(thiserror::Error, Debug, PartialEq)]
20    pub enum PauserError {
21        #[error("{0}")]
22        Std(#[from] StdError),
23
24        #[error("The contract is paused")]
25        IsPaused,
26
27        #[error("Not authorized to execute the method")]
28        Unauthorized,
29    }
30
31    impl From<CanExecuteResponse> for Result<(), PauserError> {
32        fn from(value: CanExecuteResponse) -> Self {
33            let status: CanExecuteFlag = value.into();
34            match status {
35                CanExecuteFlag::CanExecute => Ok(()),
36                CanExecuteFlag::Paused => Err(PauserError::IsPaused),
37                CanExecuteFlag::Unauthorized => Err(PauserError::Unauthorized),
38            }
39        }
40    }
41
42    const PAUSER: Item<Addr> = Item::new("_pauser");
43
44    /// Set the address of the pauser contract in the storage slot `_pauser`.
45    /// [`assert_can_execute`] will query the pauser contract at this address.
46    pub fn set_pauser(store: &mut dyn Storage, addr: &Addr) -> StdResult<()> {
47        PAUSER.save(store, addr)
48    }
49
50    /// Get the address of the pauser contract from the storage slot `_pauser`.
51    /// If [`set_pauser`] has not been called, it will return an [StdError::NotFound].
52    pub fn get_pauser(store: &dyn Storage) -> StdResult<Addr> {
53        PAUSER.may_load(store)?.ok_or(StdError::not_found("pauser"))
54    }
55
56    /// Assert that the `ExecuteMsg` can be executed without restrictions.
57    /// Requires [`set_pauser`] to be set in the `instantiate()` message.
58    pub fn assert_can_execute(
59        deps: Deps,
60        env: &Env,
61        info: &MessageInfo,
62        msg: &dyn ToString,
63    ) -> Result<(), PauserError> {
64        let addr = PAUSER.load(deps.storage)?;
65        let method = msg.to_string();
66
67        let query_msg = QueryMsg::CanExecute {
68            contract: env.contract.address.to_string(),
69            sender: info.sender.to_string(),
70            method,
71        };
72        let response: CanExecuteResponse = deps.querier.query_wasm_smart(addr, &query_msg)?;
73        response.into()
74    }
75}