1use crate::prelude::*;
8use std::collections::HashMap;
9
10use cw_storage_plus::{Key, KeyDeserialize, PrimaryKey};
11use once_cell::sync::Lazy;
12
13#[derive(Debug, Clone, Copy)]
15pub enum ShutdownWallet {
16 KillSwitch,
18 WindDown,
20}
21
22#[cw_serde]
24#[derive(enum_iterator::Sequence, Copy, Hash, Eq, PartialOrd, Ord)]
25pub enum ShutdownImpact {
26 NewTrades,
30 ClosePositions,
32 OwnerActions,
34 DepositLiquidity,
36 WithdrawLiquidity,
40 Staking,
42 Unstaking,
44 TransferPositions,
46 TransferLp,
48 SetPrice,
50 TransferDaoFees,
52 Crank,
54 SetManualPrice,
56}
57
58impl ShutdownImpact {
59 pub fn can_perform(self, shutdown_wallet: ShutdownWallet) -> bool {
61 match (shutdown_wallet, self) {
62 (ShutdownWallet::KillSwitch, _) => true,
63 (ShutdownWallet::WindDown, ShutdownImpact::NewTrades) => true,
64 (ShutdownWallet::WindDown, ShutdownImpact::ClosePositions) => false,
65 (ShutdownWallet::WindDown, ShutdownImpact::OwnerActions) => false,
66 (ShutdownWallet::WindDown, ShutdownImpact::DepositLiquidity) => true,
67 (ShutdownWallet::WindDown, ShutdownImpact::WithdrawLiquidity) => false,
68 (ShutdownWallet::WindDown, ShutdownImpact::Staking) => true,
69 (ShutdownWallet::WindDown, ShutdownImpact::Unstaking) => false,
70 (ShutdownWallet::WindDown, ShutdownImpact::TransferPositions) => false,
71 (ShutdownWallet::WindDown, ShutdownImpact::TransferLp) => false,
72 (ShutdownWallet::WindDown, ShutdownImpact::SetPrice) => false,
73 (ShutdownWallet::WindDown, ShutdownImpact::TransferDaoFees) => false,
74 (ShutdownWallet::WindDown, ShutdownImpact::Crank) => false,
75 (ShutdownWallet::WindDown, ShutdownImpact::SetManualPrice) => false,
76 }
77 }
78
79 pub fn ensure_can_perform(self, shutdown_wallet: ShutdownWallet) -> Result<()> {
81 if self.can_perform(shutdown_wallet) {
82 Ok(())
83 } else {
84 let msg = format!("{shutdown_wallet:?} cannot perform {self:?}");
85 Err(anyhow!(PerpError::auth(ErrorDomain::Factory, msg)))
86 }
87 }
88
89 pub fn for_market_execute_msg(
91 msg: &crate::contracts::market::entry::ExecuteMsg,
92 ) -> Option<Self> {
93 use crate::contracts::market::entry::ExecuteMsg;
94 match msg {
95 ExecuteMsg::Owner(_) => Some(Self::OwnerActions),
96 ExecuteMsg::Receive { .. } => None,
98 ExecuteMsg::OpenPosition { .. } => Some(Self::NewTrades),
99 ExecuteMsg::UpdatePositionAddCollateralImpactLeverage { .. } => Some(Self::NewTrades),
100 ExecuteMsg::UpdatePositionAddCollateralImpactSize { .. } => Some(Self::NewTrades),
101 ExecuteMsg::UpdatePositionRemoveCollateralImpactLeverage { .. } => {
102 Some(Self::NewTrades)
103 }
104 ExecuteMsg::UpdatePositionRemoveCollateralImpactSize { .. } => Some(Self::NewTrades),
105 ExecuteMsg::UpdatePositionLeverage { .. } => Some(Self::NewTrades),
106 ExecuteMsg::UpdatePositionMaxGains { .. } => Some(Self::NewTrades),
107 ExecuteMsg::UpdatePositionTakeProfitPrice { .. } => Some(Self::NewTrades),
108 ExecuteMsg::UpdatePositionStopLossPrice { .. } => Some(Self::NewTrades),
109 #[allow(deprecated)]
110 ExecuteMsg::SetTriggerOrder { .. } => Some(Self::NewTrades),
111 ExecuteMsg::ClosePosition { .. } => Some(Self::ClosePositions),
112 ExecuteMsg::DepositLiquidity { .. } => Some(Self::DepositLiquidity),
113 ExecuteMsg::ReinvestYield { .. } => Some(Self::DepositLiquidity),
114 ExecuteMsg::WithdrawLiquidity { .. } => Some(Self::WithdrawLiquidity),
115 ExecuteMsg::ClaimYield {} => Some(Self::WithdrawLiquidity),
116 ExecuteMsg::StakeLp { .. } => Some(Self::Staking),
117 ExecuteMsg::UnstakeXlp { .. } => Some(Self::Unstaking),
118 ExecuteMsg::StopUnstakingXlp {} => Some(Self::Unstaking),
119 ExecuteMsg::CollectUnstakedLp {} => Some(Self::Unstaking),
120 ExecuteMsg::Crank { .. } => Some(Self::Crank),
121 ExecuteMsg::NftProxy { .. } => Some(Self::TransferPositions),
122 ExecuteMsg::LiquidityTokenProxy { .. } => Some(Self::TransferLp),
123 ExecuteMsg::TransferDaoFees { .. } => Some(Self::TransferDaoFees),
124 ExecuteMsg::CloseAllPositions {} => None,
125 ExecuteMsg::PlaceLimitOrder { .. } => Some(Self::NewTrades),
126 ExecuteMsg::CancelLimitOrder { .. } => Some(Self::ClosePositions),
127 ExecuteMsg::ProvideCrankFunds {} => Some(Self::Crank),
128 ExecuteMsg::SetManualPrice { .. } => Some(Self::SetManualPrice),
129
130 ExecuteMsg::PerformDeferredExec { .. } => None,
132 }
133 }
134}
135
136#[cw_serde]
138#[derive(Copy)]
139pub enum ShutdownEffect {
140 Disable,
142 Enable,
144}
145
146impl ShutdownImpact {
147 pub(crate) fn as_bytes(self) -> &'static [u8] {
149 static LOOKUP: Lazy<HashMap<ShutdownImpact, Vec<u8>>> = Lazy::new(|| {
150 enum_iterator::all::<ShutdownImpact>()
151 .map(|x| (x, format!("{x:?}").into_bytes()))
152 .collect()
153 });
154 LOOKUP
155 .get(&self)
156 .expect("Impossible! ShutdownImpact::as_bytes failed")
157 }
158
159 pub(crate) fn try_from_bytes(bytes: &[u8]) -> Result<Self> {
161 static LOOKUP: Lazy<HashMap<Vec<u8>, ShutdownImpact>> = Lazy::new(|| {
162 enum_iterator::all::<ShutdownImpact>()
163 .map(|x| (format!("{x:?}").into_bytes(), x))
164 .collect()
165 });
166 LOOKUP.get(bytes).copied().with_context(|| {
167 format!(
168 "Unable to parse as ShutdownImpact: {:?}",
169 std::str::from_utf8(bytes)
170 )
171 })
172 }
173}
174
175impl KeyDeserialize for ShutdownImpact {
176 type Output = ShutdownImpact;
177
178 const KEY_ELEMS: u16 = 1;
179
180 fn from_vec(value: Vec<u8>) -> cosmwasm_std::StdResult<Self::Output> {
181 ShutdownImpact::try_from_bytes(&value)
182 .map_err(|x| cosmwasm_std::StdError::parse_err("ShutdownImpact", x))
183 }
184}
185
186impl<'a> PrimaryKey<'a> for ShutdownImpact {
187 type Prefix = ();
188 type SubPrefix = ();
189 type Suffix = Self;
190 type SuperSuffix = Self;
191
192 fn key(&self) -> Vec<Key> {
193 vec![Key::Ref(self.as_bytes())]
194 }
195}