Swap
The DLMM contract only provides two basic methods for flash swaps: flash_swap
and repay_flash_swap
. To execute a complete swap operation, developers need to compose these primitive functions together with additional logic, handling the borrowing, trading, and repayment sequences within a single transaction.
1. Using Existing Swap Methods
DLMM Router Contract
Function Parameters
pool: Pool object ID
coin_a: Input Coin object. This method is swap A to B, so input Coin A.
config: Reference to the global config for validations
by_amount_in: Fix input coin amount or output coin amout.
amount: If by_amount_in equals true, it means input amount coin A, else it means output amount coin B.
amount_limit: If by_amount_in equals true, it means the min output amount for coin B , else it means the max amount for coin A.
confg: Reference to the global config for validations
mainnet
0xf31b605d117f959b9730e8c07b08b856cb05143c5e81d5751c90d2979e82f599
testnet
0x88bb33e9eff2fccab980a0e4b43fc4572abd08f08304d47a20d3e4e99d94d159
versioned: Versioned object for version checking
mainnet
0x05370b2d656612dd5759cbe80463de301e3b94a921dfc72dd9daa2ecdeb2d0a8
testnet
0xa710caae87b2129acc97fbb98ea7011e3137c3291b02c0fcce866d67d5d9e8d0
clock: Clock object for timestamp operations. (0x6)
Location
swap module
Contract Code
public fun swap_a2b<CoinTypeA, CoinTypeB>(
pool: &mut Pool<CoinTypeA, CoinTypeB>,
coin_a: &mut Coin<CoinTypeA>,
by_amount_in: bool,
amount: u64,
amount_limit: u64,
config: &GlobalConfig,
versioned: &Versioned,
clock: &Clock,
ctx: &mut TxContext,
) {
let mut coin_b = coin::zero<CoinTypeB>(ctx);
swap_(
pool,
coin_a,
&mut coin_b,
true,
by_amount_in,
amount,
amount_limit,
versioned,
config,
clock,
ctx,
);
send_coin(coin_b, ctx.sender());
}
public fun swap_b2a<CoinTypeA, CoinTypeB>(
pool: &mut Pool<CoinTypeA, CoinTypeB>,
coin_b: &mut Coin<CoinTypeB>,
by_amount_in: bool,
amount: u64,
amount_limit: u64,
config: &GlobalConfig,
versioned: &Versioned,
clock: &Clock,
ctx: &mut TxContext,
) {
let mut coin_a = coin::zero<CoinTypeA>(ctx);
swap_(
pool,
&mut coin_a,
coin_b,
false,
by_amount_in,
amount,
amount_limit,
versioned,
config,
clock,
ctx,
);
send_coin(coin_a, ctx.sender());
}
public fun swap_a2b_with_partner<CoinTypeA, CoinTypeB>(
pool: &mut Pool<CoinTypeA, CoinTypeB>,
partner: &mut Partner,
coin_a: &mut Coin<CoinTypeA>,
by_amount_in: bool,
amount: u64,
amount_limit: u64,
config: &GlobalConfig,
versioned: &Versioned,
clock: &Clock,
ctx: &mut TxContext,
) {
let mut coin_b = coin::zero<CoinTypeB>(ctx);
swap_with_partner_(
pool,
partner,
coin_a,
&mut coin_b,
true,
by_amount_in,
amount,
amount_limit,
config,
versioned,
clock,
ctx,
);
send_coin(coin_b, ctx.sender());
}
public fun swap_b2a_with_partner<CoinTypeA, CoinTypeB>(
pool: &mut Pool<CoinTypeA, CoinTypeB>,
partner: &mut Partner,
coin_b: &mut Coin<CoinTypeB>,
by_amount_in: bool,
amount: u64,
amount_limit: u64,
config: &GlobalConfig,
versioned: &Versioned,
clock: &Clock,
ctx: &mut TxContext,
) {
let mut coin_a = coin::zero<CoinTypeA>(ctx);
swap_with_partner_(
pool,
partner,
&mut coin_a,
coin_b,
false,
by_amount_in,
amount,
amount_limit,
config,
versioned,
clock,
ctx,
);
send_coin(coin_a, ctx.sender());
}
2. Construct Your Own Swap Method.
Function Parameters
pool : one mutable reference of the 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.
confg: Reference to the global config for validations
networkglobal config object idmainnet
0xf31b605d117f959b9730e8c07b08b856cb05143c5e81d5751c90d2979e82f599
testnet
0x88bb33e9eff2fccab980a0e4b43fc4572abd08f08304d47a20d3e4e99d94d159
versioned: Versioned object for version checking
networkversioned config object idmainnet
0x05370b2d656612dd5759cbe80463de301e3b94a921dfc72dd9daa2ecdeb2d0a8
testnet
0xa710caae87b2129acc97fbb98ea7011e3137c3291b02c0fcce866d67d5d9e8d0
clock: Clock object for timestamp operations. (0x6)
You can implement swaps like the following examples. This is divided into two instances: one with a partner and the other without.
fun swap_<CoinTypeA, CoinTypeB>(
pool: &mut Pool<CoinTypeA, CoinTypeB>,
coin_a: &mut Coin<CoinTypeA>,
coin_b: &mut Coin<CoinTypeB>,
a2b: bool,
by_amount_in: bool,
amount: u64,
amount_limit: u64,
versioned: &Versioned,
config: &GlobalConfig,
clock: &Clock,
ctx: &mut TxContext,
) {
let (receive_a, receive_b, flash_receipt) = pool::flash_swap<CoinTypeA, CoinTypeB>(
pool,
a2b,
by_amount_in,
amount,
config,
versioned,
clock,
ctx,
);
let (in_amount, out_amount) = (
flash_receipt.pay_amount(),
if (a2b) receive_b.value() else receive_a.value(),
);
if (by_amount_in) {
assert!(in_amount == amount, ESwapAmountIncorrect);
assert!(out_amount >= amount_limit, EAmountOutBelowMinLimit);
} else {
assert!(out_amount == amount, ESwapAmountIncorrect);
assert!(in_amount <= amount_limit, EAmountInAboveMaxLimit);
};
let (pay_coin_a, pay_coin_b) = if (a2b) {
assert!(coin_a.value() >= in_amount, ENotEnoughCoin);
(coin_a.split(in_amount, ctx).into_balance(), balance::zero<CoinTypeB>())
} else {
assert!(coin_b.value() >= in_amount, ENotEnoughCoin);
(balance::zero<CoinTypeA>(), coin_b.split(in_amount, ctx).into_balance())
};
pool::repay_flash_swap<CoinTypeA, CoinTypeB>(
pool,
pay_coin_a,
pay_coin_b,
flash_receipt,
versioned,
);
coin_a.join(receive_a.into_coin(ctx));
coin_b.join(receive_b.into_coin(ctx));
}
fun swap_with_partner_<CoinTypeA, CoinTypeB>(
pool: &mut Pool<CoinTypeA, CoinTypeB>,
partner: &mut Partner,
coin_a: &mut Coin<CoinTypeA>,
coin_b: &mut Coin<CoinTypeB>,
a2b: bool,
by_amount_in: bool,
amount: u64,
amount_limit: u64,
config: &GlobalConfig,
versioned: &Versioned,
clock: &Clock,
ctx: &mut TxContext,
) {
let (receive_a, receive_b, flash_receipt) = pool::flash_swap_with_partner<CoinTypeA, CoinTypeB>(
pool,
partner,
a2b,
by_amount_in,
amount,
config,
versioned,
clock,
ctx,
);
let (in_amount, out_amount) = (
flash_receipt.pay_amount(),
if (a2b) receive_b.value() else receive_a.value(),
);
if (by_amount_in) {
assert!(in_amount == amount, ESwapAmountIncorrect);
assert!(out_amount >= amount_limit, EAmountOutBelowMinLimit);
} else {
assert!(out_amount == amount, ESwapAmountIncorrect);
assert!(in_amount <= amount_limit, EAmountInAboveMaxLimit);
};
let (pay_coin_a, pay_coin_b) = if (a2b) {
assert!(coin_a.value() >= in_amount, ENotEnoughCoin);
(coin_a.split(in_amount, ctx).into_balance(), balance::zero<CoinTypeB>())
} else {
assert!(coin_b.value() >= in_amount, ENotEnoughCoin);
(balance::zero<CoinTypeA>(), coin_b.split(in_amount, ctx).into_balance())
};
pool::repay_flash_swap_with_partner<CoinTypeA, CoinTypeB>(
pool,
partner,
pay_coin_a,
pay_coin_b,
flash_receipt,
versioned,
);
coin_a.join(receive_a.into_coin(ctx));
coin_b.join(receive_b.into_coin(ctx));
}
Last updated