1. Swap
Note:
In the Cetus CLMM contract, both the flash swap and the repay flash swap functions do not care for slippage. If you integrate these functions into your contract, you must implement your own slippage checks.
Function params
config: the reference of clmm globalconfig object. you can see details at
pool: one mutable reference of the pool.
coins_a: vector of coin a. this type is the same as the coin a of pool.
coins_b: vector of coin b. this type is the same as the coin b of pool.
a2b: the swap direction, a2b equals true means sold coin a then get coin b.
by_amount_in: when it equal true means want to fix the amount of input coin. when it equal false means want to fix the amount of output coin.
amount: when by_amount_in equals true , amount means the quantity of input coin, when by_amount_in equals false , amount means the quantity of output coin.
amount_limit: the threshold value of coin. when by_amount_in equals true , it means the minimum amount about received coin, when by_amount_in equals false , it means the maximum amount abount sold.
sqrt_price_limit: two constant of sqrt price(x64 fixed-point number). When a2b equals true , it equals 4295048016, when a2b equals false , it equals 79226673515401279992447579055.
clock: the sui clock object.
You can implement swaps like the following example.
Copy // Swap
fun swap< CoinTypeA , CoinTypeB >(
config : & GlobalConfig ,
pool : &mut Pool < CoinTypeA , CoinTypeB >,
coins_a : vector< Coin < CoinTypeA >>,
coins_b : vector< Coin < CoinTypeB >>,
a2b : bool ,
by_amount_in : bool ,
amount : u64 ,
amount_limit : u64 ,
sqrt_price_limit : u128 ,
clock : & Clock ,
ctx : &mut TxContext
) {
let (coin_a, coin_b) = ( merge_coins (coins_a, ctx), merge_coins (coins_b, ctx));
let (receive_a, receive_b, flash_receipt) = pool :: flash_swap< CoinTypeA , CoinTypeB >(
config,
pool,
a2b,
by_amount_in,
amount,
sqrt_price_limit,
clock
);
let (in_amount, out_amount) = (
pool :: swap_pay_amount ( & flash_receipt),
if (a2b) balance :: value ( & receive_b) else balance :: value ( & receive_a)
);
// pay for flash swap
let (pay_coin_a, pay_coin_b) = if (a2b) {
(coin :: into_balance (coin :: split ( &mut coin_a, in_amount, ctx)), balance :: zero< CoinTypeB >())
} else {
(balance :: zero< CoinTypeA >(), coin :: into_balance (coin :: split ( &mut coin_b, in_amount, ctx)))
};
coin :: join ( &mut coin_b, coin :: from_balance (receive_b, ctx));
coin :: join ( &mut coin_a, coin :: from_balance (receive_a, ctx));
pool :: repay_flash_swap< CoinTypeA , CoinTypeB >(
config,
pool,
pay_coin_a,
pay_coin_b,
flash_receipt
);
// ... send coins
}
/// Swap with partner.
fun swap_with_partner< CoinTypeA , CoinTypeB >(
config : & GlobalConfig ,
pool : &mut Pool < CoinTypeA , CoinTypeB >,
partner : &mut Partner ,
coins_a : vector< Coin < CoinTypeA >>,
coins_b : vector< Coin < CoinTypeB >>,
a2b : bool ,
by_amount_in : bool ,
amount : u64 ,
amount_limit : u64 ,
sqrt_price_limit : u128 ,
clock : & Clock ,
ctx : &mut TxContext
) {
let (coin_a, coin_b) = ( merge_coins (coins_a, ctx), merge_coins (coins_b, ctx));
let (receive_a, receive_b, flash_receipt) = pool :: flash_swap_with_partner< CoinTypeA , CoinTypeB >(
config,
pool,
partner,
a2b,
by_amount_in,
amount,
sqrt_price_limit,
clock
);
let (in_amount, out_amount) = (
pool :: swap_pay_amount ( & flash_receipt),
if (a2b) balance :: value ( & receive_b) else balance :: value ( & receive_a)
);
// pay for flash swap
let (pay_coin_a, pay_coin_b) = if (a2b) {
(coin :: into_balance (coin :: split ( &mut coin_a, in_amount, ctx)), balance :: zero< CoinTypeB >())
} else {
(balance :: zero< CoinTypeA >(), coin :: into_balance (coin :: split ( &mut coin_b, in_amount, ctx)))
};
coin :: join ( &mut coin_b, coin :: from_balance (receive_b, ctx));
coin :: join ( &mut coin_a, coin :: from_balance (receive_a, ctx));
pool :: repay_flash_swap_with_partner< CoinTypeA , CoinTypeB >(
config,
pool,
partner,
pay_coin_a,
pay_coin_b,
flash_receipt
);
// ... send coins
}
2. Swap a to b
The details of params can see in swap part.
Copy public entry fun swap_a2b< CoinTypeA , CoinTypeB >(
config : & GlobalConfig ,
pool : &mut Pool < CoinTypeA , CoinTypeB >,
coins_a : vector< Coin < CoinTypeA >>,
by_amount_in : bool ,
amount : u64 ,
amount_limit : u64 ,
sqrt_price_limit : u128 ,
clock : & Clock ,
ctx : &mut TxContext
) {
swap (
config,
pool,
coins_a,
vector :: empty (),
true ,
by_amount_in,
amount,
amount_limit,
sqrt_price_limit,
clock,
ctx
);
}
3. Swap b to a
The details of params can see in swap part.
Copy public entry fun swap_b2a< CoinTypeA , CoinTypeB >(
config : & GlobalConfig ,
pool : &mut Pool < CoinTypeA , CoinTypeB >,
coins_b : vector< Coin < CoinTypeB >>,
by_amount_in : bool ,
amount : u64 ,
amount_limit : u64 ,
sqrt_price_limit : u128 ,
clock : & Clock ,
ctx : &mut TxContext
) {
swap (
config,
pool,
vector :: empty (),
coins_b,
false ,
by_amount_in,
amount,
amount_limit,
sqrt_price_limit,
clock,
ctx
);
}
4. Swap a to b with partner
The details of params can see in swap part.
Copy public entry fun swap_a2b_with_partner< CoinTypeA , CoinTypeB >(
config : & GlobalConfig ,
pool : &mut Pool < CoinTypeA , CoinTypeB >,
partner : &mut Partner ,
coins_a : vector< Coin < CoinTypeA >>,
by_amount_in : bool ,
amount : u64 ,
amount_limit : u64 ,
sqrt_price_limit : u128 ,
clock : & Clock ,
ctx : &mut TxContext
) {
swap_with_partner (
config,
pool,
partner,
coins_a,
vector :: empty (),
true ,
by_amount_in,
amount,
amount_limit,
sqrt_price_limit,
clock,
ctx
);
}
5. Swap b to a with partner
The details of params can see in swap part.
Copy public entry fun swap_b2a_with_partner< CoinTypeA , CoinTypeB >(
config : & GlobalConfig ,
pool : &mut Pool < CoinTypeA , CoinTypeB >,
partner : &mut Partner ,
coins_b : vector< Coin < CoinTypeB >>,
by_amount_in : bool ,
amount : u64 ,
amount_limit : u64 ,
sqrt_price_limit : u128 ,
clock : & Clock ,
ctx : &mut TxContext
) {
swap_with_partner (
config,
pool,
partner,
vector :: empty (),
coins_b,
false ,
by_amount_in,
amount,
amount_limit,
sqrt_price_limit,
clock,
ctx
);
}
6. Repay add liquidity
Function param
amount_limit_a: the max reply amount abount coinA.
amount_limit_b: the max reply amount abount coinB.
Copy fun repay_add_liquidity< CoinTypeA , CoinTypeB >(
config : & GlobalConfig ,
pool : &mut Pool < CoinTypeA , CoinTypeB >,
receipt : AddLiquidityReceipt < CoinTypeA , CoinTypeB >,
coins_a : vector< Coin < CoinTypeA >>,
coins_b : vector< Coin < CoinTypeB >>,
amount_limit_a : u64 ,
amount_limit_b : u64 ,
ctx : &mut TxContext
) {
let (amount_need_a, amount_need_b) = pool :: add_liquidity_pay_amount ( & receipt);
// let (balance_a, balance_b) = (
// coin::into_balance(coin::split(&mut coin_a, amount_need_a, ctx)),
// coin::into_balance(coin::split(&mut coin_b, amount_need_b, ctx)),
// );
pool :: repay_add_liquidity (config, pool, balance_a, balance_b, receipt);
// ...
}
7. Pre swap clmmpool/sources/pool
Copy /// The step swap result
struct SwapStepResult has copy, drop, store {
current_sqrt_price : u128 ,
target_sqrt_price : u128 ,
current_liquidity : u128 ,
amount_in : u64 ,
amount_out : u64 ,
fee_amount : u64 ,
remainer_amount : u64
}
/// The calculated swap result
struct CalculatedSwapResult has copy, drop, store {
amount_in : u64 ,
amount_out : u64 ,
fee_amount : u64 ,
fee_rate : u64 ,
after_sqrt_price : u128 ,
is_exceed : bool ,
step_results : vector< SwapStepResult >
}
// Calculate Swap Result
public fun calculate_swap_result< CoinTypeA , CoinTypeB >(
pool : & Pool < CoinTypeA , CoinTypeB >,
a2b : bool ,
by_amount_in : bool ,
amount : u64 ,
) : CalculatedSwapResult {}