Skip to main content

Liquidity Provisioning

Overview

To provide liquidity to a specific DeDust pool, you must supply both assets. After doing so, the pool issues LP tokens to the depositor's address.

Due to TON's limitations, executing two transfers simultaneously isn't feasible. Thus, the balances of user deposits must be retained until the LP tokens are distributed.

To manage this process, the DeDust Protocol uses a Liquidity Deposit contract. This contract is activated when one of the assets is deposited and automatically terminates after the pool has either accepted the liquidity or the deposit has been withdrawn.

Deposit liquidity

image

To add liquidity to a Pool (A, B), deposit asset A into Vault (A) and asset B into Vault (B). That's all.

flow

In order to deposit liquidity, you should deposit two assets. After the first deposit DeDust deploys a temporary “liquidity deposit contract” which stores information about deposited assets. In DEX but not in pool yet. As soon as balances reach target balances It deposits liquidity to a pool, a pool mints LP to a user. At this moment this “liquidity deposit” contract gets destroyed.

Now, let's attempt to add some liquidity to the Pool (TON, DUST).

Step 1. Prepare input

Next, we'll need both assets and targetBalances to be identical for each deposit.

TypeScript

import { Asset } from '@dedust/sdk';

/* ... */

const tonAmount = toNano("5"); // 5 TON
const dustAmount = toNano("10"); // 10 DUST

const TON = Asset.native();
const DUST = Asset.jetton(DUST_ADDRESS);

const assets: [Asset, Asset] = [TON, DUST];
const targetBalances: [bigint, bigint] = [tonAmount, dustAmount];

Step 2. Deposit TON to Vault (TON)

TypeScript

import { PoolType } from '@dedust/sdk';

/* ... */

const tonVault = tonClient.open(await factory.getNativeVault());

await tonVault.sendDepositLiquidity(sender, {
poolType: PoolType.VOLATILE,
assets,
targetBalances,
amount: tonAmount,
});

Step 3. Deposit DUST to Vault (DUST)

TypeScript

import { JettonRoot, PoolType, VaultJetton } from '@dedust/sdk';

/* ... */

const dustRoot = tonClient.open(JettonRoot.createFromAddress(DUST_ADDRESS));
const dustWallet = tonClient.open(await dustRoot.getWallet(sender.address));

await dustWallet.sendTransfer(sender, toNano('0.5'), {
amount: dustAmount,
destination: dustVault.address,
responseAddress: sender.address,
forwardAmount: toNano('0.4'),
forwardPayload: VaultJetton.createDepositLiquidityPayload({
poolType: PoolType.VOLATILE,
assets,
targetBalances,
}),
});
estimate the output value

You can get it by using this getter on the pool where you want to add liquidity:
https://github.com/dedust-io/sdk/blob/ecd9ee9a8ddbee74c7432f8755e4b3192932d5d5/src/contracts/dex/pool/Pool.ts#L75

note

if target balances reached - user gets LP and excess of DUST.
For example - 1 TON + 0.1 DUST: https://tonviewer.com/transaction/ce3aa7520f512efdd45986901191f78f61332793f5e1d1f4c7d7cf09977efaf7

Withdraw liquidity

image

To withdraw liquidity, we need to burn LP tokens. Here's how:

TypeScript

const pool = tonClient.open(await factory.getPool(PoolType.VOLATILE, [TON, DUST]));
const lpWallet = tonClient.open(await pool.getWallet(sender.address));

await lpWallet.sendBurn(sender, toNano('0.5'), {
amount: await lpWallet.getBalance(),
});

Cancel pending deposits

image

The deposit contract expects both tokens for mint lp. If one of the tokens has not yet been sent, the deposit will be in pending status. To return funds from the pending, you need to send a cancellation of the deposit.

TypeScript

const liquidityDeposit = tonClient.open(
await factory.getLiquidityDeposit({
ownerAddress: sender.address,
poolType: PoolType.VOLATILE,
assets,
}),
);

await liquidityDeposit.sendCancelDeposit(sender, {});