💱Swap Pairs
The Astroport marketplace where anyone can trade their wares
1. Overview
At launch, Astroport will only support two pool types:
Stableswap Invariant Pools
Constant Product Pools
Depending on your use-cases and needs as well as the types of assets you want to integrate, one of these pools will be better than the other.
The contract code for the constant product pool can be found here and the code for the stableswap invariant pool is here.
2. Walkthrough
Providing Liquidity
Before calling the provide_liquidity function, users will have to approve the pool to take tokens from their wallets.
provide_liquidity
When an address executes the provide_liquidity
operation, it provides liquidity by sending a user's native or token assets to the pool.
The provide_liquidity
operation takes in the following parameters:
assets: [Asset; 2]
The type of assets in the pool. Can include a CW-20 contract_addr
or a native_token
denomination
slippage_tolerance: Option <Decimal>
The slippage tolerance for providing liquidity. Ensures that the LP transaction goes through only if the price in the pool moves less than the specified tolerance
auto_stake: Option <Bool>
Determines whether the newly minted LP tokens are also staked in the Generator contract in the same transaction
receiver: Option <String>
The receiver of the newly minted LP tokens
Providing Liquidity Without Specifying Slippage Tolerance
The provide_liquidity
operation, along with most operations in this walkthrough, works in the same way for both constant product and stableswap pools. This tutorial will use the ANC-UST Astroport pair for constant product pools and the bLUNA-LUNA Astroport pair for stableswap pools.
{
"provide_liquidity": {
"assets": [
{
"info": {
"token": {
"contract_addr": "terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76"
}
},
"amount": "1000000"
},
{
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
],
}
}
Providing Liquidity With Slippage Tolerance
slippage_tolerance
is an object of type [`Option<Decimal>`]
. It is used to specify how much the pool price can move until the provided liquidity transaction goes through.
{
"provide_liquidity": {
"assets": [
{
"info": {
"token": {
"contract_addr": "terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76"
}
},
"amount": "1000000"
},
{
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
],
"slippage_tolerance": "0.01",
}
}
Single-sided Liquidity Provision in Stableswap Pools
Liquidity providers can single side LP in stableswap pools (add only one of the tokens). LPs need to call the provide_liquidity
function and set the amount
for one of the pair tokens to "0". This can only be done for pools that already have liquidity (not for empty pools).
{
"provide_liquidity": {
"assets": [
{
"info": {
"token": {
"contract_addr": "terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp"
}
},
"amount": "1000000"
},
{
"info": {
"native_token": {
"denom": "uluna"
}
},
"amount": "0"
}
],
"slippage_tolerance": "0"
}
}
Receiver & Autostake
The receiver
and auto_stake
parameters are optional as well.
receiver
is an object of type [`Option<String>`]
. Calling the provide_liquidity
operation with a custom receiver allows you to specify where to send the resulting LP tokens. If no custom receiver
is specified, the pair will mint LP tokens for the function caller.
auto_stake
is an object of type [`Option<Bool>`]
. Calling the provide_liquidity
operation with auto_stake
astrue
allows LP tokens to automatically be staked in the Generator contract (if the LP tokens currently get ASTRO or 3rd party emissions). If auto_stake
is not specified, LP tokens will just be minted for the recipient.
{
"provide_liquidity": {
"assets": [
{
"info": {
"token": {
"contract_addr": "terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76"
}
},
"amount": "1000000"
},
{
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
],
"slippage_tolerance": "0.01",
"auto_stake": true,
"receiver": "terra..."
}
}
Withdrawing Liquidity
withdraw_liquidity
withdraw_liquidity
The withdraw_liquidity
operation burns LP tokens and withdraws liquidity from a pool.
{
"withdraw_liquidity": {}
}
pair
The withdraw_liquidity
operation must be sent to the LP token contract associated with the pool from which you want to withdraw liquidity. You can find the associated LP token contract for a given pool by calling the pair
query in the Astroport pair contract.
{
"pair": {}
}
receive
The pool will process the withdraw_liquidity
function through the receive
operation which receives a message and processes it depending on the receiving template.
{
"receive": {
"sender": "terra...",
"amount": "123",
"msg": "<base64_encoded_json_string>"
}
}
Simulations & Reverse Simulations
simulation
simulation
The simulation
query for a given Astroport Pair contract simulates a swap and returns the spread and commission amounts. The query takes in an offer_asset
which can include a CW-20 contract_addr
or a native_token
denomination depending on the pair.
Constant Product Pairs
In the case of the ANC-UST Astroport Pair, we can query simulation
and specify the offer_asset
as either a CW-20 contract_addr
for ANC or a native_token
denomination for UST.
The query returns a return_amount
with the latest exchange rate for the pool, along with the spread_amount
, and the commission_amount
.
{
"simulation": {
"offer_asset": {
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
}
}
Stableswap Pairs
The simulation
query works the same for stableswap pools. In the case of the bLUNA-LUNA Astroport Pair, we can specify the offer_asset
as either a CW-20 contract_addr
for bLUNA or a native_token
denomination for LUNA.
{
"simulation": {
"offer_asset": {
"info": {
"token": {
"contract_addr": "terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp"
}
},
"amount": "1000000"
}
}
}
reverse_simulation
reverse_simulation
The reverse_simulation
query for a given Astroport Pair contract reverse simulates a swap (specifies the ask instead of the offer) and returns the spread and commission amounts. The query takes in an offer_asset
which can include a CW-20 contract_addr
or a native_token
denomination depending on the pair.
Constant Product Pairs
In the case of the ANC-UST Astroport Pair, we can query reverse_simulation
and specify the ask_asset
as either a CW-20 contract_addr
for ANC or a native_token
denomination for UST.
The query returns an offer_amount
with the latest exchange rate for the pool, along with the spread_amount
, and the commission_amount
.
{
"reverse_simulation": {
"ask_asset": {
"info": {
"native_token": {
"denom": "uusd"
}
},
"amount": "1000000"
}
}
}
Stableswap Pairs
The reverse_simulation
query works the same for stableswap pools. In the case of the bLUNA-LUNA Astroport Pair, we can specify the ask_asset
as either a CW-20 contract_addr
for bLUNA or a native_token
denomination for LUNA.
{
"reverse_simulation": {
"ask_asset": {
"info": {
"token": {
"contract_addr": "terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp"
}
},
"amount": "1000000"
}
}
}
share
Similar to the simulation
and reserve_simulation
queries, the share
query accepts an amount of LP tokens and returns information about the share of the pool represented by that LP token amount. The query can be used to simulate the amount of assets someone would get from the pool if they were to burn a specific amount of LP tokens.
{
"share": {
"amount": "123"
}
}
Querying Data
config
The stableswap invariant algorithm uses an amplification parameter A that determines how close the stableswap curve should be to the constant product curve; an amplification value of 0 (A = 0) achieves results identical to the constant product pool algorithm; higher values of A push the curve closer to the constant price curve, resulting in lower slippage for exchange rates close to 1:1.
To fetch the current amplification for a stableswap pool, an address can call the config
query on the associated Astroport pair contract for the pool. config
returns control settings including a key-value pair of params
and a base64 encoded string. In the case of the bLUNA-LUNA pair, the encoded base64 string returns an amp
of 10.
{
"config": {}
}
pair
To determine whether a given pool is a Constant Product ("xyk") or a Stableswap ("stable") pool, an address can call the pair
query on a given Astroport pair contract. The query returns the pair_type
along with additional information, such as the asset_infos
for the pool, the contract_addr
, and the liquidity_token address.
{
"pair": {}
}
pool
pool
An address can query the pool
operation to return the amount of tokens in the pool for all assets as well as the amount of LP tokens issued.
{
"pool": {}
}
share
share
An address can query the share
operation to return the amount of assets someone would get from the pool if they were to burn a specific amount of LP tokens.
{
"share": {
"amount": "123"
}
}
cumulative_prices
cumulative_prices
An address the cumulative_prices
operation to return the cumulative prices for the assets in the pair.
{
"cumulative_prices": {}
}
fee_info
fee_info
To determine the fee charged on swaps for a specific pool and the division of profits from fees between LPs and governance, an address can call the fee_info
query on the Astroport Factory contract.
The query takes in a pair_type
and returns the fee_address
(Maker contract), the total_fee_bps
, and the maker_fee_bps.
In the case of Constant Product pools like ANC-UST, the total fee is 0.3% with 2/3 going to LPs and 1/3 to governance.
With a 1% slippage tolerance, amountUSTMin
(the minimum amount of UST to LP) should be set to 198 UST, and amountASSETMin
(the minimum amount of ASSET
to LP) should be set to .99 ASSET
. This means that, in a worst case scenario, liquidity will be added at a pool rate of 198 ASSET
/1 UST or 202.02 UST/1 ASSET
(200 UST + .99 ASSET
).
{
"fee_info": {
"pair_type": {
"xyk": {}
}
}
}
3. Notes on Slippage
Liquidity Provision
If an LP specifies a slippage tolerance when providing liquidity (either in a Constant Product or a Stableswap pool), the pool contract makes sure that the transaction goes through only if the pool price does not change more than the tolerance.
As an example, let's say someone LPs in a pool and specifies a 1% slippage tolerance. The user LPs 200 UST and 1 ASSET.
With a 1% slippage tolerance, amountUSTMin
(the minimum amount of UST to LP) should be set to 198 UST, and amountASSETMin
(the minimum amount of ASSET
to LP) should be set to .99 ASSET
. This means that, in a worst case scenario, liquidity will be added at a pool rate of 198 ASSET
/1 UST or 202.02 UST/1 ASSET
(200 UST + .99 ASSET
).
If the contract cannot add liquidity within these bounds (because the pool ratio changed more than the tolerance), the transaction will revert.
Trading
Astroport has two options to protect traders against slippage during swaps:
Provide
max_spread
- the spread is calculated as the difference between the ask amount (using the constant pool price) before and after the swap operation. Oncemax_spread
is set, it will be compared against the actual swap spread. In case the swap spread exceeds the provided max limit, the swap will fail. Note that the spread is calculated before commission deduction in order to properly represent the pool's ratio changeProvide
max_spread
+belief_price
- ifbelief_price
is provided in combination withmax_spread
, the pool will check the difference between the return amount (usingbelief_price
) and the real pool priceProvide
max_spread
- the spread is calculated as the difference between the ask amount (using the constant pool price) before and after the swap operation. Oncemax_spread
is set, it will be compared against the actual swap spread. In case the swap spread exceeds the provided max limit, the swap will fail. Note that the spread is calculated before commission deduction in order to properly represent the pool's ratio changeProvide
max_spread
+belief_price
- ifbelief_price
is provided in combination withmax_spread
, the pool will check the difference between the return amount (usingbelief_price
) and the real pool price
Please note that Astroport has the default value for the spread set to 0.5% and the max allowed spread set to 50%.
Last updated
Was this helpful?