Considering the features of TVM and the rapidly evolving world of DeFi, we've developed the following design.

Asset

Unlike many popular protocols designed to work exclusively with a single asset type (e.g., only with ERC-20 and not with the native coin), developers often resort to solutions like "wrapped native coins" (e.g. WETH for ETH, WTON / pTON for TON). This approach inherently consumes more gas.

Stepping away from the usual, we introduced the Asset concept.

Asset serves as an abstraction over specific asset types.

This simplifies the swap process as the type of asset used doesn't matter.

Additionally, we can easily integrate new asset types (e.g., extra-currencies or assets from other chains) to ensure we always remain at the forefront of the constantly evolving DeFi landscape.

Here is TL-B schema of Asset:

native$0000 = Asset;
jetton$0001 workchain_id:int8 address:uint256 = Asset;

// Upcoming
extra_currency$0010 currency_id:int32 = Asset;

You might argue that supporting all these asset types complicates the pool's logic.

Abstraction lets you add new assets by defining them and handling two actions: receiving and transferring.

This is where our other concept, the Vault, comes into play.

Vault

Supporting even just two asset types (TON and jettons) within the Pool can overcomplicate the code. To address this, we introduced a separate component named Vault.

Importantly, the Vault isn't a singular contract but a class of contracts. Each of these implements a specific API tailored for interacting with a distinct asset type.

Currently, we have two implementations, with a third on the way:

  • Native Vault - Handles the native coin (Toncoin).
  • Jetton Vault - Manages jettons).
  • Extra-Currency Vault (upcoming) - Designed for TON extra-currencies.

Vault accepts incoming transfers and just informs Pool that "user A wants to swap 100 X to Y", but keep holding received 100 X. After that, Pool informs another Vault (that's responsible for asset Y) to payout some Y to a user.

This mechanism not only simplifies the logic of each individual component but also facilitates the implementation of ultra-cheap multi-hop swaps. This efficiency arises because we're adjusting reserve calculations without physically transferring assets.

Pool

To recap what was discussed earlier, the Pool handles curve mathematics and tracks its reserves.

To clarify, the Pool isn't a single contract but rather a class of contracts that follow to the Pool API.

DeDust offers two main implementations:

  • Volatile Pool - Operates based on the commonly used "Constant Product" formula: x * y = k.
    Stable-Swap Pool - Optimized for assets of near-equal value (e.g. USDT / USDC, TON / stTON). It uses the formula: x3 • y + y3 • x = k.

Factory

The Factory is a straightforward yet critically important contract.

It's tasked with creating other contracts (such as various types of pools or vaults).

Additionally, the Factory facilitates the location of a specific contract.

Liquidity Deposit

This is a short-lived contract responsible for a user depositing liquidity into a pool.

It's deployed when one of the assets is accepted and destroyed after the pool either accepts or rejects the liquidity.