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

network
global config object id

mainnet

0xf31b605d117f959b9730e8c07b08b856cb05143c5e81d5751c90d2979e82f599

testnet

0x88bb33e9eff2fccab980a0e4b43fc4572abd08f08304d47a20d3e4e99d94d159

  • versioned: Versioned object for version checking

network
versioned config object id

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

    network
    global config object id

    mainnet

    0xf31b605d117f959b9730e8c07b08b856cb05143c5e81d5751c90d2979e82f599

    testnet

    0x88bb33e9eff2fccab980a0e4b43fc4572abd08f08304d47a20d3e4e99d94d159

  • versioned: Versioned object for version checking

    network
    versioned config object id

    mainnet

    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