levana_perpswap_cosmos/
auth.rs

1use std::fmt::Display;
2
3use crate::error::{ErrorDomain, PerpError};
4use crate::namespace;
5use crate::storage::load_external_item;
6use anyhow::{anyhow, Result};
7use cosmwasm_schema::cw_serde;
8use cosmwasm_std::{Addr, Empty, QuerierWrapper};
9
10/// Check that an addr satisfies auth checks
11#[cw_serde]
12pub enum AuthCheck {
13    /// The owner addr for runtime administration. not necessarily the same as migration admin
14    Owner,
15    /// Any specific address
16    Addr(Addr),
17    /// The market wind down address, used to gate the close all positions command.
18    WindDown,
19}
20
21impl Display for AuthCheck {
22    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23        match self {
24            AuthCheck::Owner => f.write_str("protocol owner"),
25            AuthCheck::Addr(a) => a.fmt(f),
26            AuthCheck::WindDown => f.write_str("market wind down"),
27        }
28    }
29}
30
31/// Ensure that the given address passes the specified [AuthCheck].
32pub fn assert_auth(
33    factory_addr: &Addr,
34    querier: &QuerierWrapper<Empty>,
35    addr: &Addr,
36    check: AuthCheck,
37) -> Result<()> {
38    let success = match &check {
39        AuthCheck::Owner => {
40            let owner_addr: Addr =
41                load_external_item(querier, factory_addr, namespace::OWNER_ADDR.as_bytes())?;
42            addr == owner_addr
43        }
44        AuthCheck::Addr(role_addr) => addr == role_addr,
45        AuthCheck::WindDown => {
46            let wind_down_addr: Addr =
47                load_external_item(querier, factory_addr, namespace::WIND_DOWN_ADDR.as_bytes())?;
48            addr == wind_down_addr
49        }
50    };
51
52    if success {
53        Ok(())
54    } else {
55        Err(anyhow!(PerpError::auth(
56            ErrorDomain::Default,
57            format!("failed auth, actual address: {addr}, check against: {check}")
58        )))
59    }
60}