Smart Contract API

Create a Pair

createPair

/// SwapFactory.cdc

pub fun createPair(
    token0Vault: @FungibleToken.Vault,
    token1Vault: @FungibleToken.Vault,
    accountCreationFee: @FungibleToken.Vault,
    stableMode: Bool
): Address
  • Example transaction create_pair_usdc_fusd.cdc

import FlowToken from 0x1654653399040a61
import FungibleToken from 0xf233dcee88fe0abe
import SwapFactory from 0xb063c16cac85dbd1

// Deploy a SwapPair given token{0|1}'s TokenName and contract address.
//`stableMode` specifies whether the pair uses Uniswap-V2 algorithm (stableMode:false) or Solidly-Stableswap algorithm (stableMode:true).
transaction(Token0Name: String, Token0Addr: Address, Token1Name: String, Token1Addr: Address, stableMode: Bool) {
    prepare(userAccount: AuthAccount) {
        let flowVaultRef = userAccount.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault)!
        assert(flowVaultRef.balance >= 0.002, message: "Insufficient balance to create pair, minimum balance requirement: 0.002 flow")
        let accountCreationFeeVault <- flowVaultRef.withdraw(amount: 0.001)
        
        let token0Vault <- getAccount(Token0Addr).contracts.borrow<&FungibleToken>(name: Token0Name)!.createEmptyVault()
        let token1Vault <- getAccount(Token1Addr).contracts.borrow<&FungibleToken>(name: Token1Name)!.createEmptyVault()
        SwapFactory.createPair(token0Vault: <-token0Vault, token1Vault: <-token1Vault, accountCreationFee: <-accountCreationFeeVault, stableMode: stableMode)
    }
}

Get Pair & LpToken Info

Get Pairs' Addresses

Param
Type
Comments

from

UInt64

Start Index

to

UInt64

End Index

Return Value

[Address]

An array of deployed trading pair addresses

  • Get number of all deployed trading pairs and an array of deployed trading pair addresses.

  • Example script get_all_pair_addresses.cdc:

getPairInfo

Param
Type
Comments

token0Key

String

token0's unique identifier, e.g.: A.3c5959b568896393.FUSD

token1Key

String

token1's unique identifier, e.g.: A.b19436aae4d94622.FiatToken

Return Value

AnyStruct?

nil if the pair doesn't exist, otherwise returns detailed pair info, e.g.:

  • Example script to get PairInfo given the pair address:

  • Example script `get_all_pair_infos.cdc`:

LpTokenCollection

Liquidity Provider (LP) of a trading pair will receive corresponding FT (i.e. LpToken) representing LP's pro rata share of that pair. LP may provide liquidity to different trading pairs and receive multiple different LpTokens. All these LpTokens are grouped within the LpTokenCollection resource, with methods exposing LpToken details:

  • Example script to check all the LPed pairs and liquidity shares of a given account:

Swap

A straightforward way to contruct a Swap transaction is to use the SwapRouter, which provides a set of useful methods below.

Calculate output / input amount

getAmountsOut

Param
Type
Comments

amountIn

UFix64

Input token amount for the FT tokenKeyPath[0], e.g. 50.0

tokenKeyPath

[String]

An array of FT identifiers denoting the chained-swap path, e.g.: [A.3c5959b568896393.FUSD, A.1654653399040a61.FlowToken, A.b19436aae4d94622.FiatToken] => denoting the swap path of [FUSD -> Flow -> USDC].

tokenKeyPath.length must be >= 2, pools for each consecutive pair of FTs must exist and have liquidity.

Return Vaule

[UFix64]

Calculated maximum output FT amounts following the given swap path, e.g. [50.0, 10.0, 48.0]

  • Given the input amount of a FT, with an array of FT identifiers denoting the chained-swap path, calculates all subsequent maximum output token amounts.

  • Useful for calculating output token amounts before calling Perform chained-swap

getAmountsIn

Param
Type
Comments

amountOut

UFix64

Expected output amount of the FT to receive, e.g. 48.0

tokenKeyPath

[String]

An array of FT identifiers denoting the chained-swap path, e.g.: [A.3c5959b568896393.FUSD, A.1654653399040a61.FlowToken, A.b19436aae4d94622.FiatToken] => denoting the swap path of [FUSD -> Flow -> USDC].

tokenKeyPath.length must be >= 2, pools for each consecutive pair of FTs must exist and have liquidity.

Return Value

[UFix64]

Calculated minimum input FT amounts following the given swap path, e.g. [50.0, 10.0, 48.0]

  • Given the expected output amount of a FT, with an array of FT identifiers denoting the chained-swap path, calculates the minimum input FT amounts required to buy the given amountOut.

  • Useful for calculating input token amounts before calling Perform chained-swap

Perform chained-swap

swapExactTokensForTokens

Param
Type
Comments

exactVaultIn

@FT.Vault

Input FT to sell, its full balance will be used.

amountOutMin

UFix64

The minimum amount of output token that must be received, otherwise the tx will revert.

tokenKeyPath

[String]

An array of FT identifiers denoting the chained-swap path, e.g.: [A.3c5959b568896393.FUSD, A.1654653399040a61.FlowToken, A.b19436aae4d94622.FiatToken] => denoting the swap path of [FUSD -> Flow -> USDC].

tokenKeyPath.length must be >= 2, pools for each consecutive pair of FTs must exist and have liquidity.

deadline

UFix64

Unix timestamp after which the tx will revert.

Return Value

@FT.Vault

Output FT resource

  • To receive as many output FT as possible for swapping the exact amount of input FT, by following the given swap path.

  • Example transaction swap_exact_flow_to_usdc.cdc:

swapTokensForExactTokens

Param
Type
Comments

vaultInMax

@FT.Vault

Input FT to sell, whose balance is the maximum amount can be used before the tx reverts. Any remaining input token will be put in returnValue[1].

exactAmountOut

UFix64

The exact amount of output FT expected to receive.

tokenKeyPath

[String]

An array of FT identifiers denoting the chained-swap path, e.g.: [A.3c5959b568896393.FUSD, A.1654653399040a61.FlowToken, A.b19436aae4d94622.FiatToken] => denoting the swap path of [FUSD -> Flow -> USDC].

tokenKeyPath.length must be >= 2, pools for each consecutive pair of FTs must exist and have liquidity.

deadline

UFix64

Unix timestamp after which the tx will revert.

Return Value

@[FT.Vault]

2-element array of FT resources. * returnValue[0]: output token resource, whose balance will be exactAmountOut. * returnValue[1]: Any remaining input token resource.

  • To receive the exact amount of output FT for swapping as few input FT as possible, by following the given swap path.

  • Example transaction swap_flow_to_exact_usdc.cdc:

  • Note: Using flow-cli tool in the commandline environment, or fcl-js library as long with tx.cdc / script.cdc to interact with smart contracts directly.

  • *SwapRouter provides an easy way to perform chained swaps among non-stableswap pairs, but it won't work acrossing stableswap pairs: as for any two given tokens, there could be two SwapPair for them, the existing SwapRouter interfaces cannot easily support it. To perform chained swap among non-stableswap pairs and stableswap pairs, one needs to take an address array of pairs and understand SwapPair's raw apis (read below).

Helper functions and Raw apis

Helper functions in SwapConfig

Raw apis in SwapPair

Add & Remove Liquidity

AddLiquidity

  • It's not recommended to use the low-level addLiquidity method directly, unless you're the 1st LP to set the initial price.

  • Use below example transaction to do slippage check and add liquidity at the ideal ratio:

RemoveLiquidity

  • Example transaction below to burn lpToken and deposit back removed two-sided liquidities:

Build a TWAP Oracle

  • DEX-based TWAP (time-weighted-average-price) oracles can be built using the last cumulative prices recorded in each SwapPair.

  • However, to correctly use & integrate the twap-oracle into your projects, you must ensure the sampling of the cumulative price data are kept up to date. As long as your oracle is up to date, you can depend on it to produce average prices.

Check below 2 examples for the sampling (update()) and twap-data consuming (twap()).

Fixed-window TWAP oracle example:

Sliding-window TWAP oracle example

Flashloan

Flashloan Interfaces

Example usage

Last updated