Skip to main content

Constant Product Pools

Overview​

The constant product pool uses the widely known xy=k formula. More details around how the pool functions can be found here.

A constant product pool holds two assets. New pools mint a tokenfactory LP denom, factory/<pool address>/astroport/share. The pool's owner for update_config is the factory owner.

InstantiateMsg​

Pools are instantiated by the factory, not directly. The factory passes this message to the pool; you only choose pair_type, asset_infos and init_params in create_pair.

json
pair.rs
Copy

_20
{
_20
"pair_type": {
_20
"xyk": {}
_20
},
_20
"asset_infos": [
_20
{
_20
"native_token": {
_20
"denom": "uluna"
_20
}
_20
},
_20
{
_20
"native_token": {
_20
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_20
}
_20
}
_20
],
_20
"token_code_id": 69,
_20
"factory_addr": "terra14x9fr055x5hvr48hzy2t4q7kvjvfttsvxusa4xsdcy702mnzsvuqprer8r",
_20
"init_params": "eyJ0cmFja19hc3NldF9iYWxhbmNlcyI6dHJ1ZX0="
_20
}

ParamsTypeDescription
pair_typePairTypeThe pool type
asset_infosVec<AssetInfo>The two assets in the pool
token_code_idu64CW20 code ID kept in the factory config. New pools use a tokenfactory LP denom, so it isn't used for the LP token
factory_addrStringThe factory contract address
init_paramsOption<Binary>Optional base64-encoded XYKPoolParams: {"track_asset_balances": true} records asset balances per block for asset_balance_at. It can't be turned off later

ExecuteMsg​

receive​

CW20 receive hook. A CW20 offer asset is swapped by sending it to the pool with the CW20 send message and a base64-encoded swap hook. CW20 tokens can't be swapped with swap directly.

json
pair.rs
Copy

_7
{
_7
"receive": {
_7
"sender": "terra1...",
_7
"amount": "1000000",
_7
"msg": "<base64_encoded_json_string>"
_7
}
_7
}

ParamsTypeDescription
receiveCw20ReceiveMsgCW20 receive message

Cw20HookMsg::Swap​

The hook embedded in msg. The offer asset and amount come from the CW20 transfer.

json
pair.rs
Copy

_12
{
_12
"swap": {
_12
"ask_asset_info": {
_12
"native_token": {
_12
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_12
}
_12
},
_12
"belief_price": "0.25",
_12
"max_spread": "0.005",
_12
"to": "terra1..."
_12
}
_12
}

ParamsTypeDescription
ask_asset_infoOption<AssetInfo>The asset to receive. Optional in a two-asset pool
belief_priceOption<Decimal>The price the trader expects, used with max_spread
max_spreadOption<Decimal>Maximum spread allowed. Defaults to 0.5%, at most 50%
toOption<String>Recipient of the ask asset. Defaults to the CW20 sender

provide_liquidity​

Deposits assets into the pool and mints LP tokens. Native assets are attached to the message as funds. CW20 assets are pulled with transfer_from, so you must first increase the pool's allowance for them. On the first deposit, a small amount of LP is minted to the pool itself and stays locked.

json
pair.rs
Copy

_26
{
_26
"provide_liquidity": {
_26
"assets": [
_26
{
_26
"info": {
_26
"native_token": {
_26
"denom": "uluna"
_26
}
_26
},
_26
"amount": "1000000"
_26
},
_26
{
_26
"info": {
_26
"native_token": {
_26
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_26
}
_26
},
_26
"amount": "1000000"
_26
}
_26
],
_26
"slippage_tolerance": "0.01",
_26
"auto_stake": true,
_26
"receiver": "terra1...",
_26
"min_lp_to_receive": "990000"
_26
}
_26
}

ParamsTypeDescription
assetsVec<Asset>The assets to deposit
slippage_toleranceOption<Decimal>Fails the deposit if the pool price moves more than this against the deposit ratio
auto_stakeOption<bool>If true, the minted LP tokens are staked in the Incentives contract on behalf of receiver. Defaults to false
receiverOption<String>Receiver of the LP tokens. Defaults to the sender
min_lp_to_receiveOption<Uint128>Fails the deposit if fewer LP tokens would be minted

withdraw_liquidity​

Burns LP tokens and returns the matching share of each pool asset. Attach the LP tokens (the pool's tokenfactory denom, for example factory/terra1...pool/astroport/share) as funds. Only balanced withdrawals are allowed: leave assets empty, otherwise the call fails. LP tokens staked in Incentives must be unstaked first. Older pools with a CW20 LP token are withdrawn from by sending the LP token to the pool with a {"withdraw_liquidity":{}} hook.

json
pair.rs
Copy

_23
{
_23
"withdraw_liquidity": {
_23
"assets": [],
_23
"min_assets_to_receive": [
_23
{
_23
"info": {
_23
"native_token": {
_23
"denom": "uluna"
_23
}
_23
},
_23
"amount": "990000"
_23
},
_23
{
_23
"info": {
_23
"native_token": {
_23
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_23
}
_23
},
_23
"amount": "247000"
_23
}
_23
]
_23
}
_23
}

ParamsTypeDescription
assetsVec<Asset>Must be empty. Imbalanced withdrawals are disabled
min_assets_to_receiveOption<Vec<Asset>>Fails the withdrawal if less than these amounts would be returned

swap​

Swaps a native offer asset, attached as funds. For a CW20 offer asset use receive.

json
pair.rs
Copy

_20
{
_20
"swap": {
_20
"offer_asset": {
_20
"info": {
_20
"native_token": {
_20
"denom": "uluna"
_20
}
_20
},
_20
"amount": "1000000"
_20
},
_20
"ask_asset_info": {
_20
"native_token": {
_20
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_20
}
_20
},
_20
"belief_price": "0.25",
_20
"max_spread": "0.005",
_20
"to": "terra1..."
_20
}
_20
}

ParamsTypeDescription
offer_assetAssetThe asset and amount to swap. Must match the attached funds
ask_asset_infoOption<AssetInfo>The asset to receive. Optional in a two-asset pool
belief_priceOption<Decimal>The price the trader expects. With max_spread, the swap fails if the return is worse than this price by more than max_spread
max_spreadOption<Decimal>Maximum spread allowed, before fees. Defaults to 0.5%, at most 50%
toOption<String>Recipient of the ask asset. Defaults to the sender

update_config​

Enables or disables swap fee sharing. Only the factory owner can call it. params is a base64-encoded XYKPoolUpdateParams.

json
pair.rs
Copy

_5
{
_5
"update_config": {
_5
"params": "eyJlbmFibGVfZmVlX3NoYXJlIjp7ImZlZV9zaGFyZV9icHMiOjUwMCwiZmVlX3NoYXJlX2FkZHJlc3MiOiJ0ZXJyYTEuLi4ifX0="
_5
}
_5
}

ParamsTypeDescription
paramsBinaryBase64-encoded XYKPoolUpdateParams
VariantsDescription
enable_fee_share { fee_share_bps, fee_share_address }Sends fee_share_bps of each swap's fee to fee_share_address. Greater than 0 and at most 1000 (10%)
disable_fee_shareStops fee sharing
NOTE

Constant product pools don't support propose_new_owner, drop_ownership_proposal or claim_ownership: their owner is always the factory owner.

QueryMsg​

pair​

Returns the pool's PairInfo: its assets, address, LP denom and type.

json
pair.rs
Copy

_3
{
_3
"pair": {}
_3
}

json
Copy

_19
{
_19
"asset_infos": [
_19
{
_19
"native_token": {
_19
"denom": "uluna"
_19
}
_19
},
_19
{
_19
"native_token": {
_19
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_19
}
_19
}
_19
],
_19
"contract_addr": "terra1...pool",
_19
"liquidity_token": "factory/terra1...pool/astroport/share",
_19
"pair_type": {
_19
"xyk": {}
_19
}
_19
}

ParamsTypeDescription
asset_infosVec<AssetInfo>The pool's assets
contract_addrAddrThe pool address
liquidity_tokenStringThe LP token: a tokenfactory denom for pools created by current factories, a CW20 address for older pools
pair_typePairTypeThe pool type

pool​

Returns the pool's asset balances and the total LP supply.

json
pair.rs
Copy

_3
{
_3
"pool": {}
_3
}

PoolResponse​

json
pair.rs
Copy

_21
{
_21
"assets": [
_21
{
_21
"info": {
_21
"native_token": {
_21
"denom": "uluna"
_21
}
_21
},
_21
"amount": "1000000000"
_21
},
_21
{
_21
"info": {
_21
"native_token": {
_21
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_21
}
_21
},
_21
"amount": "250000000"
_21
}
_21
],
_21
"total_share": "500000000"
_21
}

ParamsTypeDescription
assetsVec<Asset>The assets in the pool with their amounts
total_shareUint128The total amount of LP tokens issued

config​

Returns the pool configuration.

json
pair.rs
Copy

_3
{
_3
"config": {}
_3
}

ConfigResponse​

json
pair.rs
Copy

_7
{
_7
"block_time_last": 1730700000,
_7
"params": "eyJ0cmFja19hc3NldF9iYWxhbmNlcyI6ZmFsc2UsImZlZV9zaGFyZSI6bnVsbH0=",
_7
"owner": "terra1k9j8rcyk87v5jvfla2m9wp200azegjz0eshl7n2pwv852a7ssceqsnn7pq",
_7
"factory_addr": "terra14x9fr055x5hvr48hzy2t4q7kvjvfttsvxusa4xsdcy702mnzsvuqprer8r",
_7
"tracker_addr": null
_7
}

ParamsTypeDescription
block_time_lastu64Last time the cumulative prices were updated
paramsOption<Binary>Base64-encoded XYKPoolConfig (below)
ownerAddrThe factory owner
factory_addrAddrThe factory contract address
tracker_addrOption<Addr>The tokenfactory tracker contract, if the pool has one

XYKPoolConfig​

json
pair.rs
Copy

_4
{
_4
"track_asset_balances": false,
_4
"fee_share": null
_4
}

ParamsTypeDescription
track_asset_balancesboolWhether asset balances are tracked per block
fee_shareOption<FeeShareConfig>Fee sharing, if enabled: { "bps": u16, "recipient": Addr }

share​

Returns the assets a given amount of LP tokens can be withdrawn for, as a Vec<Asset>.

json
pair.rs
Copy

_5
{
_5
"share": {
_5
"amount": "1000000"
_5
}
_5
}

ParamsTypeDescription
amountUint128The amount of LP tokens

simulation​

Simulates a swap and returns the amount received, the spread and the commission.

json
pair.rs
Copy

_17
{
_17
"simulation": {
_17
"offer_asset": {
_17
"info": {
_17
"native_token": {
_17
"denom": "uluna"
_17
}
_17
},
_17
"amount": "1000000"
_17
},
_17
"ask_asset_info": {
_17
"native_token": {
_17
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_17
}
_17
}
_17
}
_17
}

ParamsTypeDescription
offer_assetAssetThe asset and amount to swap
ask_asset_infoOption<AssetInfo>The asset to receive

SimulationResponse​

json
pair.rs
Copy

_5
{
_5
"return_amount": "249000",
_5
"spread_amount": "250",
_5
"commission_amount": "750"
_5
}

ParamsTypeDescription
return_amountUint128The amount of the ask asset returned
spread_amountUint128The spread, in the ask asset
commission_amountUint128The fee charged, in the ask asset

reverse_simulation​

Simulates a swap from the ask side: returns the offer amount needed to receive ask_asset.

json
pair.rs
Copy

_17
{
_17
"reverse_simulation": {
_17
"offer_asset_info": {
_17
"native_token": {
_17
"denom": "uluna"
_17
}
_17
},
_17
"ask_asset": {
_17
"info": {
_17
"native_token": {
_17
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_17
}
_17
},
_17
"amount": "250000"
_17
}
_17
}
_17
}

ParamsTypeDescription
offer_asset_infoOption<AssetInfo>The asset to offer
ask_assetAssetThe asset and amount to receive

ReverseSimulationResponse​

json
pair.rs
Copy

_5
{
_5
"offer_amount": "1004000",
_5
"spread_amount": "250",
_5
"commission_amount": "750"
_5
}

ParamsTypeDescription
offer_amountUint128The amount of the offer asset needed
spread_amountUint128The spread, in the ask asset
commission_amountUint128The fee charged, in the ask asset

cumulative_prices​

Returns the pool's cumulative prices, which can be sampled twice to compute a TWAP.

json
pair.rs
Copy

_3
{
_3
"cumulative_prices": {}
_3
}

CumulativePricesResponse​

json
pair.rs
Copy

_49
{
_49
"assets": [
_49
{
_49
"info": {
_49
"native_token": {
_49
"denom": "uluna"
_49
}
_49
},
_49
"amount": "1000000000"
_49
},
_49
{
_49
"info": {
_49
"native_token": {
_49
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_49
}
_49
},
_49
"amount": "250000000"
_49
}
_49
],
_49
"total_share": "500000000",
_49
"cumulative_prices": [
_49
[
_49
{
_49
"native_token": {
_49
"denom": "uluna"
_49
}
_49
},
_49
{
_49
"native_token": {
_49
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_49
}
_49
},
_49
"123456789"
_49
],
_49
[
_49
{
_49
"native_token": {
_49
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_49
}
_49
},
_49
{
_49
"native_token": {
_49
"denom": "uluna"
_49
}
_49
},
_49
"987654321"
_49
]
_49
]
_49
}

ParamsTypeDescription
assetsVec<Asset>The assets in the pool with their amounts
total_shareUint128The total amount of LP tokens issued
cumulative_pricesVec<(AssetInfo, AssetInfo, Uint128)>The cumulative price of each asset pair (offer, ask, price)

asset_balance_at​

Returns the pool's balance of an asset just before the given block height, or null if balances weren't tracked then. Balances are only tracked if the pool was created with track_asset_balances set.

json
pair.rs
Copy

_10
{
_10
"asset_balance_at": {
_10
"asset_info": {
_10
"native_token": {
_10
"denom": "uluna"
_10
}
_10
},
_10
"block_height": "22948000"
_10
}
_10
}

ParamsTypeDescription
asset_infoAssetInfoThe pool asset to query
block_heightUint64The block height

simulate_provide​

Returns the amount of LP tokens a deposit would mint, as a Uint128.

json
pair.rs
Copy

_23
{
_23
"simulate_provide": {
_23
"assets": [
_23
{
_23
"info": {
_23
"native_token": {
_23
"denom": "uluna"
_23
}
_23
},
_23
"amount": "1000000"
_23
},
_23
{
_23
"info": {
_23
"native_token": {
_23
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_23
}
_23
},
_23
"amount": "250000"
_23
}
_23
],
_23
"slippage_tolerance": "0.01"
_23
}
_23
}

ParamsTypeDescription
assetsVec<Asset>The assets to deposit
slippage_toleranceOption<Decimal>The slippage tolerance the deposit would use

simulate_withdraw​

Returns the assets a given amount of LP tokens would be withdrawn for, as a Vec<Asset>.

json
pair.rs
Copy

_5
{
_5
"simulate_withdraw": {
_5
"lp_amount": "1000000"
_5
}
_5
}

ParamsTypeDescription
lp_amountUint128The amount of LP tokens