Skip to main content

astroport/
pair.rs

1use crate::observation::OracleObservation;
2use cosmwasm_schema::{cw_serde, QueryResponses};
3
4use crate::asset::{Asset, AssetInfo, PairInfo};
5
6use crate::factory::PairType;
7use cosmwasm_std::{Addr, Binary, Decimal, Decimal256, Empty, StdError, Uint128, Uint64};
8use cw20::Cw20ReceiveMsg;
9
10/// The default swap slippage
11pub const DEFAULT_SLIPPAGE: &str = "0.005";
12/// The maximum allowed swap slippage
13pub const MAX_ALLOWED_SLIPPAGE: &str = "0.5";
14/// The maximum fee share allowed, 10%
15pub const MAX_FEE_SHARE_BPS: u16 = 1000;
16
17/// Decimal precision for TWAP results
18pub const TWAP_PRECISION: u8 = 6;
19
20/// Min safe trading size (0.00001) to calculate a price. This value considers
21/// amount in decimal form with respective token precision.
22pub const MIN_TRADE_SIZE: Decimal256 = Decimal256::raw(10000000000000);
23
24/// This structure describes the parameters used for creating a contract.
25#[cw_serde]
26pub struct InstantiateMsg {
27    /// The pair type
28    pub pair_type: PairType,
29    /// Information about assets in the pool
30    pub asset_infos: Vec<AssetInfo>,
31    /// The token contract code ID used for the tokens in the pool
32    pub token_code_id: u64,
33    /// The factory contract address
34    pub factory_addr: String,
35    /// Optional binary serialised parameters for custom pool types
36    pub init_params: Option<Binary>,
37}
38
39/// This structure describes the execute messages available in the contract.
40#[cw_serde]
41pub enum ExecuteMsgExt<C> {
42    /// Receives a message of type [`Cw20ReceiveMsg`]
43    Receive(Cw20ReceiveMsg),
44    /// ProvideLiquidity allows someone to provide liquidity in the pool
45    ProvideLiquidity {
46        /// The assets available in the pool
47        assets: Vec<Asset>,
48        /// The slippage tolerance that allows liquidity provision only if the price in the pool doesn't move too much
49        slippage_tolerance: Option<Decimal>,
50        /// Determines whether the LP tokens minted for the user is auto_staked in the Incentives contract
51        auto_stake: Option<bool>,
52        /// The receiver of LP tokens
53        receiver: Option<String>,
54        min_lp_to_receive: Option<Uint128>,
55    },
56    /// WithdrawLiquidity allows someone to withdraw liquidity from the pool
57    WithdrawLiquidity {
58        #[serde(default)]
59        assets: Vec<Asset>,
60        min_assets_to_receive: Option<Vec<Asset>>,
61    },
62    /// Swap performs a swap in the pool
63    Swap {
64        offer_asset: Asset,
65        ask_asset_info: Option<AssetInfo>,
66        belief_price: Option<Decimal>,
67        max_spread: Option<Decimal>,
68        to: Option<String>,
69    },
70    /// Update the pair configuration
71    UpdateConfig { params: Binary },
72    /// ProposeNewOwner creates a proposal to change contract ownership.
73    /// The validity period for the proposal is set in the `expires_in` variable.
74    ProposeNewOwner {
75        /// Newly proposed contract owner
76        owner: String,
77        /// The date after which this proposal expires
78        expires_in: u64,
79    },
80    /// DropOwnershipProposal removes the existing offer to change contract ownership.
81    DropOwnershipProposal {},
82    /// Used to claim contract ownership.
83    ClaimOwnership {},
84    /// Custom execute endpoints for extended pool implementations
85    Custom(C),
86}
87
88pub type ExecuteMsg = ExecuteMsgExt<Empty>;
89
90/// This structure describes a CW20 hook message.
91#[cw_serde]
92pub enum Cw20HookMsg {
93    /// Swap a given amount of asset
94    Swap {
95        ask_asset_info: Option<AssetInfo>,
96        belief_price: Option<Decimal>,
97        max_spread: Option<Decimal>,
98        to: Option<String>,
99    },
100}
101
102/// This structure describes the query messages available in the contract.
103#[cw_serde]
104#[derive(QueryResponses)]
105pub enum QueryMsg {
106    /// Returns information about a pair in an object of type [`super::asset::PairInfo`].
107    #[returns(PairInfo)]
108    Pair {},
109    /// Returns information about a pool in an object of type [`PoolResponse`].
110    #[returns(PoolResponse)]
111    Pool {},
112    /// Returns contract configuration settings in a custom [`ConfigResponse`] structure.
113    #[returns(ConfigResponse)]
114    Config {},
115    /// Returns information about the share of the pool in a vector that contains objects of type [`Asset`].
116    #[returns(Vec<Asset>)]
117    Share { amount: Uint128 },
118    /// Returns information about a swap simulation in a [`SimulationResponse`] object.
119    #[returns(SimulationResponse)]
120    Simulation {
121        offer_asset: Asset,
122        ask_asset_info: Option<AssetInfo>,
123    },
124    /// Returns information about cumulative prices in a [`ReverseSimulationResponse`] object.
125    #[returns(ReverseSimulationResponse)]
126    ReverseSimulation {
127        offer_asset_info: Option<AssetInfo>,
128        ask_asset: Asset,
129    },
130    /// Returns information about the cumulative prices in a [`CumulativePricesResponse`] object
131    #[returns(CumulativePricesResponse)]
132    CumulativePrices {},
133    /// Returns current D invariant in as a [`u128`] value
134    #[returns(Uint128)]
135    QueryComputeD {},
136    /// Returns the balance of the specified asset that was in the pool just preceeding the moment of the specified block height creation.
137    #[returns(Option<Uint128>)]
138    AssetBalanceAt {
139        asset_info: AssetInfo,
140        block_height: Uint64,
141    },
142    /// Query price from observations
143    #[returns(OracleObservation)]
144    Observe { seconds_ago: u64 },
145    /// Returns an estimation of assets received for the given amount of LP tokens
146    #[returns(Vec<Asset>)]
147    SimulateWithdraw { lp_amount: Uint128 },
148    /// Returns an estimation of shares received for the given amount of assets
149    #[returns(Uint128)]
150    SimulateProvide {
151        assets: Vec<Asset>,
152        slippage_tolerance: Option<Decimal>,
153    },
154}
155
156/// This struct is used to return a query result with the total amount of LP tokens and assets in a specific pool.
157#[cw_serde]
158pub struct PoolResponse {
159    /// The assets in the pool together with asset amounts
160    pub assets: Vec<Asset>,
161    /// The total amount of LP tokens currently issued
162    pub total_share: Uint128,
163}
164
165/// This struct is used to return a query result with the general contract configuration.
166#[cw_serde]
167pub struct ConfigResponse {
168    /// Last timestamp when the cumulative prices in the pool were updated
169    pub block_time_last: u64,
170    /// The pool's parameters
171    pub params: Option<Binary>,
172    /// The contract owner
173    pub owner: Addr,
174    /// The factory contract address
175    pub factory_addr: Addr,
176    /// Tracker contract address
177    pub tracker_addr: Option<Addr>,
178}
179
180/// Holds the configuration for fee sharing
181#[cw_serde]
182pub struct FeeShareConfig {
183    /// The fee shared with the address
184    pub bps: u16,
185    /// The share is sent to this address on every swap
186    pub recipient: Addr,
187}
188
189/// This structure holds the parameters that are returned from a swap simulation response
190#[cw_serde]
191pub struct SimulationResponse {
192    /// The amount of ask assets returned by the swap
193    pub return_amount: Uint128,
194    /// The spread used in the swap operation
195    pub spread_amount: Uint128,
196    /// The amount of fees charged by the transaction
197    pub commission_amount: Uint128,
198}
199
200/// This structure holds the parameters that are returned from a reverse swap simulation response.
201#[cw_serde]
202pub struct ReverseSimulationResponse {
203    /// The amount of offer assets returned by the reverse swap
204    pub offer_amount: Uint128,
205    /// The spread used in the swap operation
206    pub spread_amount: Uint128,
207    /// The amount of fees charged by the transaction
208    pub commission_amount: Uint128,
209}
210
211/// This structure is used to return a cumulative prices query response.
212#[cw_serde]
213pub struct CumulativePricesResponse {
214    /// The assets in the pool to query
215    pub assets: Vec<Asset>,
216    /// The total amount of LP tokens currently issued
217    pub total_share: Uint128,
218    /// The vector contains cumulative prices for each pair of assets in the pool
219    pub cumulative_prices: Vec<(AssetInfo, AssetInfo, Uint128)>,
220}
221
222/// This structure describes a migration message.
223/// We currently take no arguments for migrations.
224#[cw_serde]
225pub struct MigrateMsg {}
226
227/// This structure holds XYK pool parameters.
228#[cw_serde]
229pub struct XYKPoolParams {
230    /// Whether asset balances are tracked over blocks or not.
231    /// They will not be tracked if the parameter is ignored.
232    /// It can not be disabled later once enabled.
233    pub track_asset_balances: Option<bool>,
234}
235
236/// This structure stores a XYK pool's configuration.
237#[cw_serde]
238pub struct XYKPoolConfig {
239    /// Whether asset balances are tracked over blocks or not.
240    pub track_asset_balances: bool,
241    // The config for swap fee sharing
242    pub fee_share: Option<FeeShareConfig>,
243}
244
245/// This enum stores the option available to enable asset balances tracking over blocks.
246#[cw_serde]
247pub enum XYKPoolUpdateParams {
248    /// Enables the sharing of swap fees with an external party.
249    EnableFeeShare {
250        /// The fee shared with the fee_share_address
251        fee_share_bps: u16,
252        /// The fee_share_bps is sent to this address on every swap
253        fee_share_address: String,
254    },
255    DisableFeeShare,
256}
257
258/// This structure holds stableswap pool parameters.
259#[cw_serde]
260pub struct StablePoolParams {
261    /// The current stableswap pool amplification
262    pub amp: u64,
263    /// The contract owner
264    pub owner: Option<String>,
265}
266
267/// This structure stores a stableswap pool's configuration.
268#[cw_serde]
269pub struct StablePoolConfig {
270    /// The stableswap pool amplification
271    pub amp: Decimal,
272    // The config for swap fee sharing
273    pub fee_share: Option<FeeShareConfig>,
274}
275
276/// This enum stores the options available to start and stop changing a stableswap pool's amplification.
277#[cw_serde]
278pub enum StablePoolUpdateParams {
279    StartChangingAmp {
280        next_amp: u64,
281        next_amp_time: u64,
282    },
283    StopChangingAmp {},
284    /// Enables the sharing of swap fees with an external party.
285    EnableFeeShare {
286        /// The fee shared with the fee_share_address
287        fee_share_bps: u16,
288        /// The fee_share_bps is sent to this address on every swap
289        fee_share_address: String,
290    },
291    DisableFeeShare,
292}
293
294/// A `reply` call code ID used for sub-messages.
295#[cw_serde]
296pub enum ReplyIds {
297    CreateDenom = 1,
298    InstantiateTrackingContract = 2,
299}
300
301impl TryFrom<u64> for ReplyIds {
302    type Error = StdError;
303
304    fn try_from(value: u64) -> Result<Self, Self::Error> {
305        match value {
306            1 => Ok(ReplyIds::CreateDenom),
307            2 => Ok(ReplyIds::InstantiateTrackingContract),
308            _ => Err(StdError::ParseErr {
309                target_type: "ReplyIds".to_string(),
310                msg: "Failed to parse reply".to_string(),
311            }),
312        }
313    }
314}
315
316#[cfg(test)]
317mod tests {
318    use super::*;
319    use cosmwasm_std::{from_json, to_json_binary};
320
321    #[cw_serde]
322    pub struct LegacyConfigResponse {
323        pub block_time_last: u64,
324        pub params: Option<Binary>,
325        pub factory_addr: Addr,
326        pub owner: Addr,
327    }
328
329    #[test]
330    fn test_config_response_compatability() {
331        let ser_msg = to_json_binary(&LegacyConfigResponse {
332            block_time_last: 12,
333            params: Some(
334                to_json_binary(&StablePoolConfig {
335                    amp: Decimal::one(),
336                    fee_share: None,
337                })
338                .unwrap(),
339            ),
340            factory_addr: Addr::unchecked(""),
341            owner: Addr::unchecked(""),
342        })
343        .unwrap();
344
345        let _: ConfigResponse = from_json(&ser_msg).unwrap();
346    }
347}