Skip to main content

lotus_dex_std/
pool_manager.rs

1use std::fmt;
2
3use cosmwasm_schema::{cw_serde, QueryResponses};
4use cosmwasm_std::{Addr, Coin, Decimal, Deps, StdError, StdResult, Uint128};
5use cw_ownable::{cw_ownable_execute, cw_ownable_query};
6
7use crate::coin::is_factory_token;
8use crate::fee::PoolFee;
9
10/// The type of swap operation to perform.
11#[cw_serde]
12pub enum SwapOperation {
13    /// A swap operation that uses the LotusSwap router.
14    LotusSwap {
15        /// The token denom to swap in.
16        token_in_denom: String,
17        /// The token denom returning from the swap.
18        token_out_denom: String,
19        /// The identifier of the pool to use for the swap.
20        pool_identifier: String,
21    },
22}
23
24impl SwapOperation {
25    /// Retrieves the `token_in_denom` used for this swap operation.
26    pub fn get_input_asset_info(&self) -> &String {
27        match self {
28            SwapOperation::LotusSwap { token_in_denom, .. } => token_in_denom,
29        }
30    }
31
32    pub fn get_target_asset_info(&self) -> String {
33        match self {
34            SwapOperation::LotusSwap {
35                token_out_denom, ..
36            } => token_out_denom.clone(),
37        }
38    }
39
40    pub fn get_pool_identifer(&self) -> String {
41        match self {
42            SwapOperation::LotusSwap {
43                pool_identifier, ..
44            } => pool_identifier.clone(),
45        }
46    }
47}
48
49impl fmt::Display for SwapOperation {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        match self {
52            SwapOperation::LotusSwap {
53                token_in_denom,
54                token_out_denom,
55                pool_identifier,
56            } => write!(
57                f,
58                "LotusSwap {{ token_in_info: {token_in_denom}, token_out_info: {token_out_denom}, pool_identifier: {pool_identifier} }}"
59            ),
60        }
61    }
62}
63
64/// Contains the pool information
65#[cw_serde]
66pub struct PoolInfo {
67    /// The identifier for the pool.
68    pub pool_identifier: String,
69    /// The asset denoms for the pool.
70    pub asset_denoms: Vec<String>,
71    /// The LP denom of the pool.
72    pub lp_denom: String,
73    /// The decimals for the given asset denoms, provided in the same order as asset_denoms.
74    pub asset_decimals: Vec<u8>,
75    /// The total amount of assets in the pool.
76    pub assets: Vec<Coin>,
77    /// The fees for the pool.
78    pub pool_fees: PoolFee,
79    /// The status of the pool
80    pub status: PoolStatus,
81}
82
83/// The pool status tells what actions are enabled for this pool.
84#[cw_serde]
85pub struct PoolStatus {
86    /// Whether swaps are enabled
87    pub swaps_enabled: bool,
88    /// Whether deposits are enabled
89    pub deposits_enabled: bool,
90    /// Whether withdrawals are enabled
91    pub withdrawals_enabled: bool,
92}
93
94impl Default for PoolStatus {
95    fn default() -> Self {
96        PoolStatus {
97            swaps_enabled: true,
98            deposits_enabled: true,
99            withdrawals_enabled: true,
100        }
101    }
102}
103
104/// The contract configuration.
105#[cw_serde]
106pub struct Config {
107    /// The address where the collected fees go to.
108    pub fee_collector_addr: Addr,
109    /// How much it costs to create a pool. It helps prevent spamming of new pools.
110    pub pool_creation_fee: Coin,
111}
112
113#[cw_serde]
114pub struct InstantiateMsg {
115    /// The address where the collected fees go to.
116    pub fee_collector_addr: String,
117    /// How much it costs to create a pool. It helps prevent spamming of new pools.
118    pub pool_creation_fee: Coin,
119}
120
121#[cw_serde]
122pub struct MigrateMsg {}
123
124#[cw_ownable_execute]
125#[cw_serde]
126pub enum ExecuteMsg {
127    /// Creates a new pool.
128    CreatePool {
129        /// The asset denoms for the pool.
130        asset_denoms: Vec<String>,
131        /// The decimals for the given asset denoms, provided in the same order as `asset_denoms`.
132        asset_decimals: Vec<u8>,
133        /// The fees for the pool.
134        pool_fees: PoolFee,
135        /// The identifier for the pool.
136        pool_identifier: Option<String>,
137    },
138    /// Provides liquidity to the pool
139    ProvideLiquidity {
140        /// A percentage value representing the acceptable slippage for the operation.
141        /// When provided, if the slippage exceeds this value, the liquidity provision will not be
142        /// executed.
143        slippage_tolerance: Option<Decimal>,
144        /// The receiver of the LP
145        receiver: Option<String>,
146        /// The identifier for the pool to provide liquidity for.
147        pool_identifier: String,
148    },
149    /// Swap an offer asset to the other
150    Swap {
151        /// The return asset of the swap.
152        ask_asset_denom: String,
153        /// The minimum amount of the output (i.e., final swap operation token) required for the message to succeed.
154        minimum_receive: Option<Uint128>,
155        /// The recipient of the output tokens. If not provided, the tokens will be sent to the sender
156        /// of the message.
157        receiver: Option<String>,
158        /// The identifier for the pool to swap in.
159        pool_identifier: String,
160    },
161    /// Withdraws liquidity from the pool.
162    WithdrawLiquidity { pool_identifier: String },
163    /// Execute multiple [`SwapOperation`]s to allow for multi-hop swaps.
164    ExecuteSwapOperations {
165        /// The operations that should be performed in sequence.
166        ///
167        /// The amount in each swap will be the output from the previous swap.
168        ///
169        /// The first swap will use whatever funds are sent in the MessageInfo.
170        operations: Vec<SwapOperation>,
171        /// The minimum amount of the output (i.e., final swap operation token) required for the message to succeed.
172        minimum_receive: Option<Uint128>,
173        /// The (optional) recipient of the output tokens.
174        ///
175        /// If left unspecified, tokens will be sent to the sender of the message.
176        receiver: Option<String>,
177    },
178    /// Updates the configuration of the contract.
179    /// If a field is not specified (i.e., set to `None`), it will not be modified.
180    UpdateConfig {
181        /// The new fee collector contract address.
182        fee_collector_addr: Option<String>,
183        /// The new fee that must be paid when a pool is created.
184        pool_creation_fee: Option<Coin>,
185        /// Toggles features for a given pool, allowing fine-tuned
186        /// control over which operations are allowed, i.e. swap, deposits, withdrawals
187        feature_toggle: Option<FeatureToggle>,
188    },
189}
190
191#[cw_ownable_query]
192#[cw_serde]
193#[derive(QueryResponses)]
194pub enum QueryMsg {
195    /// Retrieves the contract's config.
196    #[returns(ConfigResponse)]
197    Config {},
198    /// Retrieves the decimals for the given asset.
199    #[returns(AssetDecimalsResponse)]
200    AssetDecimals {
201        /// The pool identifier to do the query for.
202        pool_identifier: String,
203        /// The queried denom in the given pool_identifier.
204        denom: String,
205    },
206    /// Simulates a swap.
207    #[returns(SimulationResponse)]
208    Simulation {
209        /// The offer asset to swap.
210        offer_asset: Coin,
211        /// The ask asset denom to get.
212        ask_asset_denom: String,
213        /// The pool identifier to swap in.
214        pool_identifier: String,
215    },
216    /// Simulates a reverse swap, i.e. given the ask asset, how much of the offer asset is needed
217    /// to perform the swap.
218    #[returns(ReverseSimulationResponse)]
219    ReverseSimulation {
220        /// The ask asset to get after the swap.
221        ask_asset: Coin,
222        /// The offer asset denom to input.
223        offer_asset_denom: String,
224        /// The pool identifier to swap in.
225        pool_identifier: String,
226    },
227    /// Simulates swap operations.
228    #[returns(SimulateSwapOperationsResponse)]
229    SimulateSwapOperations {
230        /// The amount to swap.
231        offer_amount: Uint128,
232        /// The operations to perform.
233        operations: Vec<SwapOperation>,
234    },
235    /// Simulates a reverse swap operations, i.e. given the ask asset, how much of the offer asset
236    /// is needed to perform the swap.
237    #[returns(ReverseSimulateSwapOperationsResponse)]
238    ReverseSimulateSwapOperations {
239        /// The amount to get after the swap.
240        ask_amount: Uint128,
241        /// The operations to perform.
242        operations: Vec<SwapOperation>,
243    },
244    /// Retrieves the pool information for the given pool identifier.
245    #[returns(PoolsResponse)]
246    Pools {
247        /// An optional parameter specifying the pool identifier to do the query for. If not
248        /// provided, it will return all pools based on the pagination parameters.
249        pool_identifier: Option<String>,
250        /// An optional parameter specifying what pool (identifier) to start searching after.
251        start_after: Option<String>,
252        /// The amount of pools to return. If unspecified, will default to a value specified by
253        /// the contract.
254        limit: Option<u32>,
255    },
256}
257
258/// The response for the `Config` query.
259#[cw_serde]
260pub struct ConfigResponse {
261    /// The contract configuration.
262    pub config: Config,
263}
264
265/// The response for the `Pools` query.
266#[cw_serde]
267pub struct PoolsResponse {
268    /// The pools information responses.
269    pub pools: Vec<PoolInfoResponse>,
270}
271
272#[cw_serde]
273pub struct PoolInfoResponse {
274    /// The pool information for the given pool identifier.
275    pub pool_info: PoolInfo,
276    /// The total LP tokens in the pool.
277    pub total_share: Coin,
278}
279
280/// The response for the `AssetDecimals` query.
281#[cw_serde]
282pub struct AssetDecimalsResponse {
283    /// The pool identifier to do the query for.
284    pub pool_identifier: String,
285    /// The queried denom in the given pool_identifier.
286    pub denom: String,
287    /// The decimals for the requested denom.
288    pub decimals: u8,
289}
290
291/// SimulationResponse returns swap simulation response
292#[cw_serde]
293pub struct SimulationResponse {
294    /// The return amount of the ask asset given the offer amount.
295    pub return_amount: Uint128,
296    /// The swap fee amount of the swap.
297    pub swap_fee_amount: Uint128,
298    /// The protocol fee amount of the swap.
299    pub protocol_fee_amount: Uint128,
300    /// The burn fee amount of the swap.
301    pub burn_fee_amount: Uint128,
302}
303
304/// ReverseSimulationResponse returns reverse swap simulation response
305#[cw_serde]
306pub struct ReverseSimulationResponse {
307    /// The amount of the offer asset needed to get the ask amount.
308    pub offer_amount: Uint128,
309    /// The swap fee amount of the swap.
310    pub swap_fee_amount: Uint128,
311    /// The protocol fee amount of the swap.
312    pub protocol_fee_amount: Uint128,
313    /// The burn fee amount of the swap.
314    pub burn_fee_amount: Uint128,
315}
316
317/// Pool feature toggle, can control whether swaps, deposits, and withdrawals are enabled.
318#[cw_serde]
319pub struct FeatureToggle {
320    /// The identifier of the pool to toggle the status of.
321    pub pool_identifier: String,
322    /// Whether or not swaps are enabled
323    pub withdrawals_enabled: Option<bool>,
324    /// Whether or not deposits are enabled
325    pub deposits_enabled: Option<bool>,
326    /// Whether or not swaps are enabled
327    pub swaps_enabled: Option<bool>,
328}
329
330/// The response for the `SimulateSwapOperations` query.
331#[cw_serde]
332pub struct SimulateSwapOperationsResponse {
333    /// The return amount of the ask asset after the swap operations.
334    pub return_amount: Uint128,
335    /// The swap fees of the swap.
336    pub swap_fees: Vec<Coin>,
337    /// The protocol fees of the swap.
338    pub protocol_fees: Vec<Coin>,
339    /// The burn fees of the swap.
340    pub burn_fees: Vec<Coin>,
341    /// The extra fees of the swap.
342    pub extra_fees: Vec<Coin>,
343}
344
345/// The response for the `ReverseSimulateSwapOperations` query.
346#[cw_serde]
347pub struct ReverseSimulateSwapOperationsResponse {
348    /// The amount of the initial token needed to get the final token after the swap operations.
349    pub offer_amount: Uint128,
350    /// The swap fees of the swap.
351    pub swap_fees: Vec<Coin>,
352    /// The protocol fees of the swap.
353    pub protocol_fees: Vec<Coin>,
354    /// The burn fees of the swap.
355    pub burn_fees: Vec<Coin>,
356}
357
358/// Gets the total supply of the given liquidity asset
359pub fn get_total_share(deps: &Deps, liquidity_asset: String) -> StdResult<Uint128> {
360    if is_factory_token(liquidity_asset.as_str()) {
361        //bank query total
362        return Ok(deps.querier.query_supply(&liquidity_asset)?.amount);
363    }
364
365    Err(StdError::generic_err("Invalid LP token"))
366}