levana_perpswap_cosmos/contracts/factory/
entry.rs

1//! Entrypoint messages for the factory
2use crate::contracts::market::entry::NewCounterTradeParams;
3use crate::prelude::*;
4use crate::{
5    contracts::market::entry::{NewCopyTradingParams, NewMarketParams},
6    shutdown::{ShutdownEffect, ShutdownImpact},
7};
8use cosmwasm_schema::{cw_serde, QueryResponses};
9use cosmwasm_std::Addr;
10use cw_storage_plus::{KeyDeserialize, Prefixer, PrimaryKey};
11use schemars::JsonSchema;
12
13/// Instantiate a new factory contract.
14#[cw_serde]
15pub struct InstantiateMsg {
16    /// The code id for the market contract
17    pub market_code_id: String,
18    /// The code id for the position_token contract
19    pub position_token_code_id: String,
20    /// The code id for the liquidity_token contract
21    pub liquidity_token_code_id: String,
22    /// The code id for the copy trading contract
23    pub copy_trading_code_id: Option<String>,
24    /// The code id for the countertrade contract
25    pub counter_trade_code_id: Option<String>,
26    /// Migration admin, needed for instantiating/migrating sub-contracts
27    pub migration_admin: RawAddr,
28    /// Perpetual swap admin address
29    pub owner: RawAddr,
30    /// DAO address
31    pub dao: RawAddr,
32    /// Kill switch address
33    pub kill_switch: RawAddr,
34    /// Wind down address
35    pub wind_down: RawAddr,
36    /// Suffix attached to all contracts instantiated by the factory
37    pub label_suffix: Option<String>,
38}
39
40/// Execute a message on the factory.
41#[allow(clippy::large_enum_variant)]
42#[cw_serde]
43pub enum ExecuteMsg {
44    /// Add a new market
45    AddMarket {
46        /// Parameters for the new market
47        new_market: NewMarketParams,
48    },
49    /// Set the market code id, i.e. if it's been migrated
50    SetMarketCodeId {
51        /// Code ID to use for future market contracts
52        code_id: String,
53    },
54    /// Set the position token code id, i.e. if it's been migrated
55    SetPositionTokenCodeId {
56        /// Code ID to use for future position token contracts
57        code_id: String,
58    },
59    /// Set the liquidity token code id, i.e. if it's been migrated
60    SetLiquidityTokenCodeId {
61        /// Code ID to use for future liquidity token contracts
62        code_id: String,
63    },
64
65    /// Change the owner addr
66    SetOwner {
67        /// New owner
68        owner: RawAddr,
69    },
70
71    /// Change the migration admin
72    SetMigrationAdmin {
73        /// New migration admin
74        migration_admin: RawAddr,
75    },
76
77    /// Change the dao addr
78    SetDao {
79        /// New DAO
80        dao: RawAddr,
81    },
82
83    /// Change the kill switch addr
84    SetKillSwitch {
85        /// New kill switch administrator
86        kill_switch: RawAddr,
87    },
88
89    /// Change the wind down addr
90    SetWindDown {
91        /// New wind down administrator
92        wind_down: RawAddr,
93    },
94
95    /// Convenience mechanism to transfer all dao fees from all markets
96    TransferAllDaoFees {},
97
98    /// Perform a shutdown on the given markets with the given impacts
99    Shutdown {
100        /// Which markets to impact? Empty list means impact all markets
101        markets: Vec<MarketId>,
102        /// Which impacts to have? Empty list means shut down all activities
103        impacts: Vec<ShutdownImpact>,
104        /// Are we disabling these impacts, or reenabling them?
105        effect: ShutdownEffect,
106    },
107
108    /// Register a referrer for the given account.
109    ///
110    /// Can only be performed once.
111    RegisterReferrer {
112        /// The wallet address of the referrer
113        addr: RawAddr,
114    },
115    /// Add new copy trading contract
116    AddCopyTrading {
117        /// Parameters for the contract
118        new_copy_trading: NewCopyTradingParams,
119    },
120    /// Add new countertrade contract
121    AddCounterTrade {
122        /// Parameters for the contract
123        new_counter_trade: NewCounterTradeParams,
124    },
125    /// Set the copy trading code id, i.e. if it's been migrated
126    SetCopyTradingCodeId {
127        /// Code ID to use for future copy trading contracts
128        code_id: String,
129    },
130    /// Set the counter trade code id, i.e. if it's been migrated
131    SetCounterTradeCodeId {
132        /// Code ID to use for future countertrade contracts
133        code_id: String,
134    },
135    /// Remove the owner from factory
136    RemoveOwner {},
137}
138
139/// Response from [QueryMsg::Markets]
140///
141/// Use [QueryMsg::MarketInfo] for details on each market.
142#[cw_serde]
143pub struct MarketsResp {
144    /// Markets maintained by this factory
145    pub markets: Vec<MarketId>,
146}
147
148/// Response from [QueryMsg::Markets]
149///
150/// Use [QueryMsg::CopyTrading] for details on copy trading contract.
151#[cw_serde]
152pub struct CopyTradingResp {
153    /// Copy trading contracts maintained by this factory
154    pub addresses: Vec<CopyTradingInfo>,
155}
156
157/// Response from [QueryMsg::Markets]
158///
159/// Use [QueryMsg::CopyTrading] for details on copy trading contract.
160#[cw_serde]
161pub struct CounterTradeResp {
162    /// Copy trading contracts maintained by this factory
163    pub addresses: Vec<CounterTradeInfo>,
164}
165
166/// Response from [QueryMsg::AddrIsContract]
167#[cw_serde]
168pub struct AddrIsContractResp {
169    /// Boolean indicating whether this is a success for failure.
170    pub is_contract: bool,
171    /// If this is a contract: what type of contract is it?
172    pub contract_type: Option<ContractType>,
173}
174
175/// The type of contract identified by [QueryMsg::AddrIsContract].
176#[cw_serde]
177pub enum ContractType {
178    /// The factory contract
179    Factory,
180    /// An LP or xLP liquidity token proxy
181    LiquidityToken,
182    /// A position NFT proxy
183    PositionToken,
184    /// A market
185    Market,
186    /// Copy trading contract
187    CopyTrading,
188    /// Countertrade contract
189    CounterTrade,
190    /// Vault contract
191    Vault,
192}
193
194/// Default limit for [QueryMsg::Markets]
195pub const MARKETS_QUERY_LIMIT_DEFAULT: u32 = 15;
196
197/// Default limit for queries.
198pub const QUERY_LIMIT_DEFAULT: u32 = 15;
199
200/// Queries available on the factory contract
201#[cw_serde]
202#[derive(QueryResponses)]
203pub enum QueryMsg {
204    /// * returns [cw2::ContractVersion]
205    #[returns(cw2::ContractVersion)]
206    Version {},
207
208    /// * returns [MarketsResp]
209    ///
210    /// All the markets
211    #[returns(MarketsResp)]
212    Markets {
213        /// Last seen market ID in a [MarketsResp] for enumeration
214        start_after: Option<MarketId>,
215        /// Defaults to [MARKETS_QUERY_LIMIT_DEFAULT]
216        limit: Option<u32>,
217    },
218
219    /// * returns [MarketInfoResponse]
220    ///
221    /// Combined query to get the market related addresses
222    #[returns(MarketInfoResponse)]
223    MarketInfo {
224        /// Market ID to look up
225        market_id: MarketId,
226    },
227
228    /// * returns [AddrIsContractResp]
229    ///
230    /// given an address, checks if it's any of the registered protocol contracts.
231    #[returns(AddrIsContractResp)]
232    AddrIsContract {
233        /// Address to check
234        addr: RawAddr,
235    },
236
237    /// * returns [FactoryOwnerResp]
238    ///
239    /// Returns information about the owners of the factory
240    #[returns(FactoryOwnerResp)]
241    FactoryOwner {},
242
243    /// * returns [ShutdownStatus]
244    #[returns(ShutdownStatus)]
245    ShutdownStatus {
246        /// Market to look up
247        market_id: MarketId,
248    },
249
250    /// * returns [CodeIds]
251    #[returns(CodeIds)]
252    CodeIds {},
253
254    /// Who referred this user, if anyone?
255    ///
256    /// * returns [GetReferrerResp]
257    #[returns(GetReferrerResp)]
258    GetReferrer {
259        /// Referee address
260        addr: RawAddr,
261    },
262
263    /// Enumerated query: who was referred by this user?
264    ///
265    /// * returns [ListRefereesResp]
266    #[returns(ListRefereesResp)]
267    ListReferees {
268        /// Referrer address
269        addr: RawAddr,
270        /// How many addresses to return at once
271        limit: Option<u32>,
272        /// Taken from [ListRefereesResp::next_start_after]
273        start_after: Option<String>,
274    },
275
276    /// Enumerated query: referee counts for all referrers.
277    ///
278    /// * returns [ListRefereeCountResp]
279    #[returns(ListRefereeCountResp)]
280    ListRefereeCount {
281        /// How many records to return at once
282        limit: Option<u32>,
283        /// Take from [ListRefereeCountResp::next_start_after]
284        start_after: Option<ListRefereeCountStartAfter>,
285    },
286
287    /// Fetch copy trading contracts
288    ///
289    /// Returns [CopyTradingResp]
290    #[returns(CopyTradingResp)]
291    CopyTrading {
292        /// Last seen [CopyTradingInfo] in a [CopyTradingResp] for enumeration
293        start_after: Option<CopyTradingInfoRaw>,
294        /// Defaults to [QUERY_LIMIT_DEFAULT]
295        limit: Option<u32>,
296    },
297    /// Fetch copy trading contract belonging to a specfic leader
298    ///
299    /// Returns [CopyTradingResp]
300    #[returns(CopyTradingResp)]
301    CopyTradingForLeader {
302        /// Leader of the contract
303        leader: RawAddr,
304        /// Last seen copy trading contract address for enumeration
305        start_after: Option<RawAddr>,
306        /// Defaults to [QUERY_LIMIT_DEFAULT]
307        limit: Option<u32>,
308    },
309    /// Fetch counter trade contracts
310    #[returns(CounterTradeResp)]
311    CounterTrade {
312        /// Last seen [MarketId] in a [CounterTradeResp] for enumeration
313        start_after: Option<MarketId>,
314        /// Defaults to [QUERY_LIMIT_DEFAULT]
315        limit: Option<u32>,
316    },
317}
318
319/// Information on owners and other protocol-wide special addresses
320#[cw_serde]
321pub struct FactoryOwnerResp {
322    /// Owner of the factory
323    pub owner: Option<Addr>,
324    /// Migration admin of the factory
325    pub admin_migration: Addr,
326    /// Wallet that receives DAO/protocol fees for all markets
327    pub dao: Addr,
328    /// Wallet that can activate kill switch shutdowns
329    pub kill_switch: Addr,
330    /// Wallet that can activate market wind downs
331    pub wind_down: Addr,
332}
333
334/// Placeholder migration message
335#[cw_serde]
336pub struct MigrateMsg {}
337
338/// Information about a specific market, returned from [QueryMsg::MarketInfo].
339#[cw_serde]
340pub struct MarketInfoResponse {
341    /// Address of the market
342    pub market_addr: Addr,
343    /// Address of the position token
344    pub position_token: Addr,
345    /// Address of the LP liquidity token
346    pub liquidity_token_lp: Addr,
347    /// Address of the xLP liquidity token
348    pub liquidity_token_xlp: Addr,
349}
350
351/// Return value from [QueryMsg::ShutdownStatus]
352#[cw_serde]
353pub struct ShutdownStatus {
354    /// Any parts of the market which have been disabled.
355    pub disabled: Vec<ShutdownImpact>,
356}
357
358impl ExecuteMsg {
359    /// Does this message require owner permissions?
360    pub fn requires_owner(&self) -> bool {
361        match self {
362            ExecuteMsg::AddMarket { .. } => true,
363            ExecuteMsg::SetMarketCodeId { .. } => true,
364            ExecuteMsg::SetPositionTokenCodeId { .. } => true,
365            ExecuteMsg::SetLiquidityTokenCodeId { .. } => true,
366            ExecuteMsg::SetCounterTradeCodeId { .. } => true,
367            ExecuteMsg::SetOwner { .. } => true,
368            ExecuteMsg::SetMigrationAdmin { .. } => true,
369            ExecuteMsg::SetDao { .. } => true,
370            ExecuteMsg::SetKillSwitch { .. } => true,
371            ExecuteMsg::SetWindDown { .. } => true,
372            ExecuteMsg::TransferAllDaoFees {} => true,
373            ExecuteMsg::RegisterReferrer { .. } => false,
374            ExecuteMsg::AddCounterTrade { .. } => false,
375            // Uses its own auth mechanism internally
376            ExecuteMsg::Shutdown { .. } => false,
377            ExecuteMsg::AddCopyTrading { .. } => false,
378            ExecuteMsg::SetCopyTradingCodeId { .. } => true,
379            ExecuteMsg::RemoveOwner {} => true,
380        }
381    }
382}
383
384/// Which code IDs are currently set for new markets
385#[cw_serde]
386pub struct CodeIds {
387    /// Market code ID
388    pub market: Uint64,
389    /// Position token proxy code ID
390    pub position_token: Uint64,
391    /// Liquidity token proxy code ID
392    pub liquidity_token: Uint64,
393    /// Countertrade code ID
394    pub counter_trade: Option<Uint64>,
395}
396
397/// Response from [QueryMsg::GetReferrer]
398#[cw_serde]
399pub enum GetReferrerResp {
400    /// No referrer registered
401    NoReferrer {},
402    /// Has a registered referrer
403    HasReferrer {
404        /// Referrer address
405        referrer: Addr,
406    },
407}
408
409/// Response from [QueryMsg::ListReferees]
410#[cw_serde]
411pub struct ListRefereesResp {
412    /// Next batch of referees
413    pub referees: Vec<Addr>,
414    /// Next value to start after
415    ///
416    /// Returns `None` if we've seen all referees
417    pub next_start_after: Option<String>,
418}
419
420/// Make a lookup key for the given referee
421///
422/// We don't follow the normal Map pattern to simplify raw queries.
423pub fn make_referrer_key(referee: &Addr) -> String {
424    format!("ref__{}", referee.as_str())
425}
426
427/// Make a lookup key for the count of referees for a referrer.
428///
429/// We don't follow the normal Map pattern to simplify raw queries.
430pub fn make_referee_count_key(referrer: &Addr) -> String {
431    format!("refcount__{}", referrer.as_str())
432}
433
434/// Response from [QueryMsg::ListRefereeCount]
435#[cw_serde]
436pub struct ListRefereeCountResp {
437    /// Counts for individual wallets
438    pub counts: Vec<RefereeCount>,
439    /// Next value to start after
440    ///
441    /// Returns `None` if we've seen all referees
442    pub next_start_after: Option<ListRefereeCountStartAfter>,
443}
444
445/// The count of referees for an individual referrer.
446#[cw_serde]
447pub struct RefereeCount {
448    /// Referrer address
449    pub referrer: Addr,
450    /// Number of referees
451    pub count: u32,
452}
453
454/// Helper for enumerated referee count queries.
455#[cw_serde]
456pub struct ListRefereeCountStartAfter {
457    /// Last referrer seen.
458    pub referrer: RawAddr,
459    /// Last count seen.
460    pub count: u32,
461}
462
463#[derive(Clone, serde::Serialize, serde::Deserialize, JsonSchema, PartialEq, Debug)]
464/// Leader address
465pub struct LeaderAddr(pub Addr);
466
467#[derive(Clone, serde::Serialize, serde::Deserialize, JsonSchema, PartialEq, Debug)]
468/// Copy trading address
469pub struct CopyTradingAddr(pub Addr);
470
471#[derive(Clone, serde::Serialize, serde::Deserialize, JsonSchema, PartialEq, Debug)]
472/// Copy trading contract information
473pub struct CopyTradingInfo {
474    /// Leader of the contract
475    pub leader: LeaderAddr,
476    /// Address of the copy trading contract
477    pub contract: CopyTradingAddr,
478}
479
480#[derive(Clone, serde::Serialize, serde::Deserialize, JsonSchema, PartialEq, Debug)]
481/// Copy trading contract information
482pub struct CounterTradeInfo {
483    /// Address of the counter trade contract
484    pub contract: CounterTradeAddr,
485    /// Associated market id of the counter trade contract
486    pub market_id: MarketId,
487}
488
489#[derive(Clone, serde::Serialize, serde::Deserialize, JsonSchema, PartialEq, Debug)]
490/// Same as [CopyTradingInfo], but has raw addresses
491pub struct CopyTradingInfoRaw {
492    /// Leader of the contract
493    pub leader: RawAddr,
494    /// Address of the copy trading contract
495    pub contract: RawAddr,
496}
497
498impl KeyDeserialize for LeaderAddr {
499    type Output = LeaderAddr;
500
501    const KEY_ELEMS: u16 = Addr::KEY_ELEMS;
502
503    fn from_vec(value: Vec<u8>) -> cosmwasm_std::StdResult<Self::Output> {
504        Addr::from_vec(value).map(LeaderAddr)
505    }
506}
507
508impl<'a> Prefixer<'a> for LeaderAddr {
509    fn prefix(&self) -> Vec<cw_storage_plus::Key> {
510        self.0.prefix()
511    }
512}
513
514impl<'a> PrimaryKey<'a> for LeaderAddr {
515    type Prefix = <Addr as PrimaryKey<'a>>::Prefix;
516    type SubPrefix = <Addr as PrimaryKey<'a>>::SubPrefix;
517    type Suffix = <Addr as PrimaryKey<'a>>::Suffix;
518    type SuperSuffix = <Addr as PrimaryKey<'a>>::SuperSuffix;
519
520    fn key(&self) -> Vec<cw_storage_plus::Key> {
521        self.0.key()
522    }
523}
524
525impl KeyDeserialize for CopyTradingAddr {
526    type Output = CopyTradingAddr;
527
528    const KEY_ELEMS: u16 = Addr::KEY_ELEMS;
529
530    fn from_vec(value: Vec<u8>) -> cosmwasm_std::StdResult<Self::Output> {
531        Addr::from_vec(value).map(CopyTradingAddr)
532    }
533}
534impl<'a> Prefixer<'a> for CopyTradingAddr {
535    fn prefix(&self) -> Vec<cw_storage_plus::Key> {
536        self.0.prefix()
537    }
538}
539
540impl<'a> PrimaryKey<'a> for CopyTradingAddr {
541    type Prefix = <Addr as PrimaryKey<'a>>::Prefix;
542    type SubPrefix = <Addr as PrimaryKey<'a>>::SubPrefix;
543    type Suffix = <Addr as PrimaryKey<'a>>::Suffix;
544    type SuperSuffix = <Addr as PrimaryKey<'a>>::SuperSuffix;
545
546    fn key(&self) -> Vec<cw_storage_plus::Key> {
547        self.0.key()
548    }
549}
550
551#[derive(Clone, serde::Serialize, serde::Deserialize, JsonSchema, PartialEq, Debug)]
552/// Counter trade contract address
553pub struct CounterTradeAddr(pub Addr);
554
555impl KeyDeserialize for CounterTradeAddr {
556    type Output = CounterTradeAddr;
557
558    const KEY_ELEMS: u16 = Addr::KEY_ELEMS;
559
560    fn from_vec(value: Vec<u8>) -> cosmwasm_std::StdResult<Self::Output> {
561        Addr::from_vec(value).map(CounterTradeAddr)
562    }
563}
564impl<'a> Prefixer<'a> for CounterTradeAddr {
565    fn prefix(&self) -> Vec<cw_storage_plus::Key> {
566        self.0.prefix()
567    }
568}
569
570impl<'a> PrimaryKey<'a> for CounterTradeAddr {
571    type Prefix = <Addr as PrimaryKey<'a>>::Prefix;
572    type SubPrefix = <Addr as PrimaryKey<'a>>::SubPrefix;
573    type Suffix = <Addr as PrimaryKey<'a>>::Suffix;
574    type SuperSuffix = <Addr as PrimaryKey<'a>>::SuperSuffix;
575
576    fn key(&self) -> Vec<cw_storage_plus::Key> {
577        self.0.key()
578    }
579}
580
581#[derive(Clone, serde::Serialize, serde::Deserialize, JsonSchema, PartialEq, Debug)]
582/// Vault contract address
583pub struct VaultAddr(pub Addr);
584
585impl KeyDeserialize for VaultAddr {
586    type Output = VaultAddr;
587
588    const KEY_ELEMS: u16 = Addr::KEY_ELEMS;
589
590    fn from_vec(value: Vec<u8>) -> cosmwasm_std::StdResult<Self::Output> {
591        Addr::from_vec(value).map(VaultAddr)
592    }
593}
594
595impl<'a> Prefixer<'a> for VaultAddr {
596    fn prefix(&self) -> Vec<cw_storage_plus::Key> {
597        self.0.prefix()
598    }
599}
600
601impl<'a> PrimaryKey<'a> for VaultAddr {
602    type Prefix = <Addr as PrimaryKey<'a>>::Prefix;
603    type SubPrefix = <Addr as PrimaryKey<'a>>::SubPrefix;
604    type Suffix = <Addr as PrimaryKey<'a>>::Suffix;
605    type SuperSuffix = <Addr as PrimaryKey<'a>>::SuperSuffix;
606
607    fn key(&self) -> Vec<cw_storage_plus::Key> {
608        self.0.key()
609    }
610}