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.
Links
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.
_20 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_20 "factory_addr": "terra14x9fr055x5hvr48hzy2t4q7kvjvfttsvxusa4xsdcy702mnzsvuqprer8r",
_20 "init_params": "eyJ0cmFja19hc3NldF9iYWxhbmNlcyI6dHJ1ZX0="
| Params | Type | Description |
|---|
pair_type | PairType | The pool type |
asset_infos | Vec<AssetInfo> | The two assets in the pool |
token_code_id | u64 | CW20 code ID kept in the factory config. New pools use a tokenfactory LP denom, so it isn't used for the LP token |
factory_addr | String | The factory contract address |
init_params | Option<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.
_7 "sender": "terra1...",
_7 "msg": "<base64_encoded_json_string>"
Cw20HookMsg::Swap
The hook embedded in msg. The offer asset and amount come from the CW20 transfer.
_12 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_12 "belief_price": "0.25",
_12 "max_spread": "0.005",
| Params | Type | Description |
|---|
ask_asset_info | Option<AssetInfo> | The asset to receive. Optional in a two-asset pool |
belief_price | Option<Decimal> | The price the trader expects, used with max_spread |
max_spread | Option<Decimal> | Maximum spread allowed. Defaults to 0.5%, at most 50% |
to | Option<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.
_26 "provide_liquidity": {
_26 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_26 "slippage_tolerance": "0.01",
_26 "receiver": "terra1...",
_26 "min_lp_to_receive": "990000"
| Params | Type | Description |
|---|
assets | Vec<Asset> | The assets to deposit |
slippage_tolerance | Option<Decimal> | Fails the deposit if the pool price moves more than this against the deposit ratio |
auto_stake | Option<bool> | If true, the minted LP tokens are staked in the Incentives contract on behalf of receiver. Defaults to false |
receiver | Option<String> | Receiver of the LP tokens. Defaults to the sender |
min_lp_to_receive | Option<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.
_23 "withdraw_liquidity": {
_23 "min_assets_to_receive": [
_23 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
| Params | Type | Description |
|---|
assets | Vec<Asset> | Must be empty. Imbalanced withdrawals are disabled |
min_assets_to_receive | Option<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.
_20 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_20 "belief_price": "0.25",
_20 "max_spread": "0.005",
| Params | Type | Description |
|---|
offer_asset | Asset | The asset and amount to swap. Must match the attached funds |
ask_asset_info | Option<AssetInfo> | The asset to receive. Optional in a two-asset pool |
belief_price | Option<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_spread | Option<Decimal> | Maximum spread allowed, before fees. Defaults to 0.5%, at most 50% |
to | Option<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.
_5 "params": "eyJlbmFibGVfZmVlX3NoYXJlIjp7ImZlZV9zaGFyZV9icHMiOjUwMCwiZmVlX3NoYXJlX2FkZHJlc3MiOiJ0ZXJyYTEuLi4ifX0="
| Params | Type | Description |
|---|
params | Binary | Base64-encoded XYKPoolUpdateParams |
| Variants | Description |
|---|
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_share | Stops 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.
_19 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_19 "contract_addr": "terra1...pool",
_19 "liquidity_token": "factory/terra1...pool/astroport/share",
| Params | Type | Description |
|---|
asset_infos | Vec<AssetInfo> | The pool's assets |
contract_addr | Addr | The pool address |
liquidity_token | String | The LP token: a tokenfactory denom for pools created by current factories, a CW20 address for older pools |
pair_type | PairType | The pool type |
pool
Returns the pool's asset balances and the total LP supply.
PoolResponse
_21 "amount": "1000000000"
_21 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_21 "amount": "250000000"
_21 "total_share": "500000000"
| Params | Type | Description |
|---|
assets | Vec<Asset> | The assets in the pool with their amounts |
total_share | Uint128 | The total amount of LP tokens issued |
config
Returns the pool configuration.
ConfigResponse
_7 "block_time_last": 1730700000,
_7 "params": "eyJ0cmFja19hc3NldF9iYWxhbmNlcyI6ZmFsc2UsImZlZV9zaGFyZSI6bnVsbH0=",
_7 "owner": "terra1k9j8rcyk87v5jvfla2m9wp200azegjz0eshl7n2pwv852a7ssceqsnn7pq",
_7 "factory_addr": "terra14x9fr055x5hvr48hzy2t4q7kvjvfttsvxusa4xsdcy702mnzsvuqprer8r",
| Params | Type | Description |
|---|
block_time_last | u64 | Last time the cumulative prices were updated |
params | Option<Binary> | Base64-encoded XYKPoolConfig (below) |
owner | Addr | The factory owner |
factory_addr | Addr | The factory contract address |
tracker_addr | Option<Addr> | The tokenfactory tracker contract, if the pool has one |
XYKPoolConfig
_4 "track_asset_balances": false,
| Params | Type | Description |
|---|
track_asset_balances | bool | Whether asset balances are tracked per block |
fee_share | Option<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>.
| Params | Type | Description |
|---|
amount | Uint128 | The amount of LP tokens |
simulation
Simulates a swap and returns the amount received, the spread and the commission.
_17 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
| Params | Type | Description |
|---|
offer_asset | Asset | The asset and amount to swap |
ask_asset_info | Option<AssetInfo> | The asset to receive |
SimulationResponse
_5 "return_amount": "249000",
_5 "spread_amount": "250",
_5 "commission_amount": "750"
| Params | Type | Description |
|---|
return_amount | Uint128 | The amount of the ask asset returned |
spread_amount | Uint128 | The spread, in the ask asset |
commission_amount | Uint128 | The fee charged, in the ask asset |
reverse_simulation
Simulates a swap from the ask side: returns the offer amount needed to receive ask_asset.
_17 "reverse_simulation": {
_17 "offer_asset_info": {
_17 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
| Params | Type | Description |
|---|
offer_asset_info | Option<AssetInfo> | The asset to offer |
ask_asset | Asset | The asset and amount to receive |
ReverseSimulationResponse
_5 "offer_amount": "1004000",
_5 "spread_amount": "250",
_5 "commission_amount": "750"
| Params | Type | Description |
|---|
offer_amount | Uint128 | The amount of the offer asset needed |
spread_amount | Uint128 | The spread, in the ask asset |
commission_amount | Uint128 | The fee charged, in the ask asset |
cumulative_prices
Returns the pool's cumulative prices, which can be sampled twice to compute a TWAP.
_3 "cumulative_prices": {}
CumulativePricesResponse
_49 "amount": "1000000000"
_49 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_49 "amount": "250000000"
_49 "total_share": "500000000",
_49 "cumulative_prices": [
_49 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_49 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
| Params | Type | Description |
|---|
assets | Vec<Asset> | The assets in the pool with their amounts |
total_share | Uint128 | The total amount of LP tokens issued |
cumulative_prices | Vec<(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.
_10 "asset_balance_at": {
_10 "block_height": "22948000"
| Params | Type | Description |
|---|
asset_info | AssetInfo | The pool asset to query |
block_height | Uint64 | The block height |
simulate_provide
Returns the amount of LP tokens a deposit would mint, as a Uint128.
_23 "simulate_provide": {
_23 "denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_23 "slippage_tolerance": "0.01"
| Params | Type | Description |
|---|
assets | Vec<Asset> | The assets to deposit |
slippage_tolerance | Option<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>.
_5 "simulate_withdraw": {
_5 "lp_amount": "1000000"
| Params | Type | Description |
|---|
lp_amount | Uint128 | The amount of LP tokens |