white_whale_std/pool_network/
pair.rs

1use crate::fee::Fee;
2use cosmwasm_schema::{cw_serde, QueryResponses};
3use cosmwasm_std::{Addr, Decimal, StdError, StdResult, Uint128};
4use cw20::Cw20ReceiveMsg;
5
6use crate::pool_network::asset::{Asset, AssetInfo, PairInfo, PairType};
7
8#[cw_serde]
9pub struct InstantiateMsg {
10    /// Asset infos
11    pub asset_infos: [AssetInfo; 2],
12    /// Token contract code id for initialization
13    pub token_code_id: u64,
14    pub asset_decimals: [u8; 2],
15    pub pool_fees: PoolFee,
16    pub fee_collector_addr: String,
17    /// The type of pair to create
18    pub pair_type: PairType,
19    /// If true, the pair will use the token factory to create the LP token. If false, it will
20    /// use a cw20 token instead.
21    pub token_factory_lp: bool,
22}
23
24#[cw_serde]
25pub enum ExecuteMsg {
26    /// Used to trigger the [Cw20HookMsg] messages
27    Receive(Cw20ReceiveMsg),
28    /// Provides liquidity to the pool
29    ProvideLiquidity {
30        assets: [Asset; 2],
31        slippage_tolerance: Option<Decimal>,
32        receiver: Option<String>,
33    },
34    /// Withdraws liquidity from the pool. Used only when the LP is a token factory token.
35    WithdrawLiquidity {},
36    /// Swap an offer asset to the other
37    Swap {
38        offer_asset: Asset,
39        belief_price: Option<Decimal>,
40        max_spread: Option<Decimal>,
41        to: Option<String>,
42    },
43    #[cfg(feature = "osmosis")]
44    /// Updates the pair pool config
45    UpdateConfig {
46        owner: Option<String>,
47        fee_collector_addr: Option<String>,
48        pool_fees: Option<PoolFee>,
49        feature_toggle: Option<FeatureToggle>,
50        cosmwasm_pool_interface: Option<String>,
51    },
52    #[cfg(not(feature = "osmosis"))]
53    /// Updates the pair pool config
54    UpdateConfig {
55        owner: Option<String>,
56        fee_collector_addr: Option<String>,
57        pool_fees: Option<PoolFee>,
58        feature_toggle: Option<FeatureToggle>,
59    },
60    /// Collects the Protocol fees accrued by the pool
61    CollectProtocolFees {},
62}
63
64#[cw_serde]
65pub enum Cw20HookMsg {
66    /// Sell a given amount of asset
67    Swap {
68        belief_price: Option<Decimal>,
69        max_spread: Option<Decimal>,
70        to: Option<String>,
71    },
72    /// Withdraws liquidity
73    WithdrawLiquidity {},
74}
75
76#[cw_serde]
77#[derive(QueryResponses)]
78pub enum QueryMsg {
79    /// Retrieves the info for the pair.
80    #[returns(PairInfo)]
81    Pair {},
82    /// Retrieves the configuration of the pool.
83    #[returns(ConfigResponse)]
84    Config {},
85    /// Retrieves the protocol fees that have been accrued. If `all_time` is `true`, it will return
86    /// the fees collected since the inception of the pool. On the other hand, if `all_time` is set
87    /// to `false`, only the fees that has been accrued by the pool but not collected by the fee
88    /// collector will be returned.
89    #[returns(ProtocolFeesResponse)]
90    ProtocolFees {
91        asset_id: Option<String>,
92        all_time: Option<bool>,
93    },
94    /// Retrieves the fees that have been burned by the pool.
95    #[returns(ProtocolFeesResponse)]
96    BurnedFees { asset_id: Option<String> },
97    /// Retrieves the pool information.
98    #[returns(PoolResponse)]
99    Pool {},
100    /// Simulates a swap.
101    #[returns(SimulationResponse)]
102    Simulation { offer_asset: Asset },
103    /// Simulates a reverse swap, i.e. given the ask asset, how much of the offer asset is needed to
104    /// perform the swap.
105    #[returns(ReverseSimulationResponse)]
106    ReverseSimulation { ask_asset: Asset },
107}
108
109/// Pool feature toggle
110#[cw_serde]
111pub struct FeatureToggle {
112    pub withdrawals_enabled: bool,
113    pub deposits_enabled: bool,
114    pub swaps_enabled: bool,
115}
116
117/// Fees used by the pools on the pool network
118#[cw_serde]
119pub struct PoolFee {
120    pub protocol_fee: Fee,
121    pub swap_fee: Fee,
122    pub burn_fee: Fee,
123    #[cfg(feature = "osmosis")]
124    pub osmosis_fee: Fee,
125}
126
127impl PoolFee {
128    /// Checks that the given [PoolFee] is valid, i.e. the fees provided are valid, and they don't
129    /// exceed 100% together
130    pub fn is_valid(&self) -> StdResult<()> {
131        self.protocol_fee.is_valid()?;
132        self.swap_fee.is_valid()?;
133        self.burn_fee.is_valid()?;
134
135        let total_fee = self.aggregate()?;
136
137        // Check if the total fee exceeds 100%
138        if total_fee >= Decimal::percent(100) {
139            return Err(StdError::generic_err("Invalid fees"));
140        }
141
142        Ok(())
143    }
144
145    /// aggregates all the fees into a single decimal
146    pub fn aggregate(&self) -> StdResult<Decimal> {
147        let total_fee = {
148            let base_fee = self
149                .protocol_fee
150                .share
151                .checked_add(self.swap_fee.share)?
152                .checked_add(self.burn_fee.share)?;
153
154            #[cfg(feature = "osmosis")]
155            {
156                base_fee.checked_add(self.osmosis_fee.share)?
157            }
158
159            #[cfg(not(feature = "osmosis"))]
160            {
161                base_fee
162            }
163        };
164
165        Ok(total_fee)
166    }
167}
168
169#[cw_serde]
170pub struct Config {
171    pub owner: Addr,
172    pub fee_collector_addr: Addr,
173    pub pool_fees: PoolFee,
174    pub feature_toggle: FeatureToggle,
175    #[cfg(feature = "osmosis")]
176    pub cosmwasm_pool_interface: Addr,
177}
178
179pub type ConfigResponse = Config;
180
181/// We define a custom struct for each query response
182#[cw_serde]
183pub struct PoolResponse {
184    pub assets: Vec<Asset>,
185    pub total_share: Uint128,
186}
187
188/// SimulationResponse returns swap simulation response
189#[cw_serde]
190pub struct SimulationResponse {
191    pub return_amount: Uint128,
192    pub spread_amount: Uint128,
193    pub swap_fee_amount: Uint128,
194    pub protocol_fee_amount: Uint128,
195    pub burn_fee_amount: Uint128,
196    #[cfg(feature = "osmosis")]
197    pub osmosis_fee_amount: Uint128,
198}
199
200/// ReverseSimulationResponse returns reverse swap simulation response
201#[cw_serde]
202pub struct ProtocolFeesResponse {
203    pub fees: Vec<Asset>,
204}
205
206/// ReverseSimulationResponse returns reverse swap simulation response
207#[cw_serde]
208pub struct ReverseSimulationResponse {
209    pub offer_amount: Uint128,
210    pub spread_amount: Uint128,
211    pub swap_fee_amount: Uint128,
212    pub protocol_fee_amount: Uint128,
213    pub burn_fee_amount: Uint128,
214    #[cfg(feature = "osmosis")]
215    pub osmosis_fee_amount: Uint128,
216}
217
218/// We currently take no arguments for migrations
219#[cw_serde]
220pub struct MigrateMsg {}