Skip to main content

Stableswap Pools

Overview​

The stableswap pool uses the 4A(Rx+Ry) + D formula, resulting in a constant price ∆x / ∆y = 1. More details around how the pool functions can be found here.

A stableswap pool holds two assets. New pools mint a tokenfactory LP denom, factory/<pool address>/astroport/share. The pool has an optional owner set in init_params; if none is set, the factory owner acts as 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
"stable": {}
_20
},
_20
"asset_infos": [
_20
{
_20
"native_token": {
_20
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_20
}
_20
},
_20
{
_20
"native_token": {
_20
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_20
}
_20
}
_20
],
_20
"token_code_id": 69,
_20
"factory_addr": "terra14x9fr055x5hvr48hzy2t4q7kvjvfttsvxusa4xsdcy702mnzsvuqprer8r",
_20
"init_params": "eyJhbXAiOjEwMCwib3duZXIiOm51bGx9"
_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>Required base64-encoded StablePoolParams: amp (amplification, greater than 0 and at most 1,000,000) and an optional owner

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": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_26
}
_26
},
_26
"amount": "1000000"
_26
},
_26
{
_26
"info": {
_26
"native_token": {
_26
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_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": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_20
}
_20
},
_20
"amount": "1000000"
_20
},
_20
"ask_asset_info": {
_20
"native_token": {
_20
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_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​

Changes the amplification or fee sharing. Only the pool owner (or the factory owner if the pool has none) can call it. params is a base64-encoded StablePoolUpdateParams.

json
pair.rs
Copy

_5
{
_5
"update_config": {
_5
"params": "eyJzdGFydF9jaGFuZ2luZ19hbXAiOnsibmV4dF9hbXAiOjIwMCwibmV4dF9hbXBfdGltZSI6MTczMTMwMDAwMH19"
_5
}
_5
}

ParamsTypeDescription
paramsBinaryBase64-encoded StablePoolUpdateParams
VariantsDescription
start_changing_amp { next_amp, next_amp_time }Moves the amplification gradually to next_amp, reached at next_amp_time. The change takes at least one day and changes amp by at most a factor of 10
stop_changing_amp {}Stops the change and keeps the current amplification
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

propose_new_owner​

Creates an offer to change the pool owner. Only the current owner can call it. The offer expires after expires_in seconds.

json
pair.rs
Copy

_6
{
_6
"propose_new_owner": {
_6
"owner": "terra1...",
_6
"expires_in": 604800
_6
}
_6
}

ParamsTypeDescription
ownerStringNewly proposed pool owner
expires_inu64Seconds until the offer expires

drop_ownership_proposal​

Removes an existing offer to change the pool owner. Only the current owner can call it.

json
pair.rs
Copy

_3
{
_3
"drop_ownership_proposal": {}
_3
}

claim_ownership​

Accepts an offer. Only the proposed owner can call it.

json
pair.rs
Copy

_3
{
_3
"claim_ownership": {}
_3
}

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": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_19
}
_19
},
_19
{
_19
"native_token": {
_19
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_19
}
_19
}
_19
],
_19
"contract_addr": "terra1...pool",
_19
"liquidity_token": "factory/terra1...pool/astroport/share",
_19
"pair_type": {
_19
"stable": {}
_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": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_21
}
_21
},
_21
"amount": "1000000000"
_21
},
_21
{
_21
"info": {
_21
"native_token": {
_21
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_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": "eyJhbXAiOiIxMDAiLCJmZWVfc2hhcmUiOm51bGx9",
_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 StablePoolConfig (below)
ownerAddrThe pool owner, or the factory owner if the pool has none
factory_addrAddrThe factory contract address
tracker_addrOption<Addr>The tokenfactory tracker contract, if the pool has one

StablePoolConfig​

json
pair.rs
Copy

_4
{
_4
"amp": "100",
_4
"fee_share": null
_4
}

ParamsTypeDescription
ampDecimalThe current amplification
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": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_17
}
_17
},
_17
"amount": "1000000"
_17
},
_17
"ask_asset_info": {
_17
"native_token": {
_17
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_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": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_17
}
_17
},
_17
"ask_asset": {
_17
"info": {
_17
"native_token": {
_17
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_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": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_49
}
_49
},
_49
"amount": "1000000000"
_49
},
_49
{
_49
"info": {
_49
"native_token": {
_49
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_49
}
_49
},
_49
"amount": "250000000"
_49
}
_49
],
_49
"total_share": "500000000",
_49
"cumulative_prices": [
_49
[
_49
{
_49
"native_token": {
_49
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_49
}
_49
},
_49
{
_49
"native_token": {
_49
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_49
}
_49
},
_49
"123456789"
_49
],
_49
[
_49
{
_49
"native_token": {
_49
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_49
}
_49
},
_49
{
_49
"native_token": {
_49
"denom": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_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)

observe​

Returns the price observed seconds_ago seconds ago. If there is no observation at that exact time, it is interpolated from the surrounding ones.

json
pair.rs
Copy

_5
{
_5
"observe": {
_5
"seconds_ago": 3600
_5
}
_5
}

ParamsTypeDescription
seconds_agou64How far back to look, in seconds

OracleObservation​

json
observation.rs
Copy

_4
{
_4
"timestamp": 1730700000,
_4
"price": "0.25"
_4
}

ParamsTypeDescription
timestampu64The time of the observation
priceDecimalThe observed price

query_compute_d​

Returns the current D invariant as a Uint128.

json
pair.rs
Copy

_3
{
_3
"query_compute_d": {}
_3
}

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": "ibc/E8481AD838C31D4FC12A504B10F9B4E2F830F8818D2735C2FFC707579B5FA60B"
_23
}
_23
},
_23
"amount": "1000000"
_23
},
_23
{
_23
"info": {
_23
"native_token": {
_23
"denom": "ibc/2C962DAB9F57FE0921435426AE75196009FAA1981BF86991203C8411F8980FDB"
_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