An open API service indexing awesome lists of open source software.

https://github.com/tact-lang/dex

WIP: Decentralized Exchange (OpenDeFi Library)
https://github.com/tact-lang/dex

decentralized-exchange dex tact tact-lang ton

Last synced: about 1 year ago
JSON representation

WIP: Decentralized Exchange (OpenDeFi Library)

Awesome Lists containing this project

README

          

# OpenDeFi Library: Decentralized Exchange in Tact, T-Dex

Tyrannosaurus rex holding TON logo

**T-Dex**: A decentralized exchange (DEX) on the TON blockchain providing
efficient exchange of various token types with a high degree of asset abstraction.

## Project Goals

- Creating a state-of-the-art fully open-source decentralized exchange (DEX)
- Minimizing commission costs through optimized architecture
- Providing a real-world example of a complex system of smart contracts, written in Tact
- Providing an example of safe and complex Jettons interaction

## Project Scope

- Smart contracts for Vaults of various asset types
- Automated Market Maker (AMM) Pool contracts
- Contracts for secure liquidity addition

## How-to and dev docs

Check these docs to learn about how T-Dex works, its semantics and how to integrate with it.

- [How to swap on T-Dex](./dev-docs/swap.md)
- How to manage liquidity, TODO
- How to work with Factory, TODO
- How to create new pool and vaults, TODO

## DEX Architecture

DEX is built on a modular architecture with clear component separation:

### Core System Components

```mermaid
graph LR
subgraph "Vault Interface"
PayoutRequest(["PayoutFromPool
(msg 0x74f7a60)
- amount: uint256
- receiver: Address"])
DepositRequest(["PartHasBeenDeposited
(msg 0xe7a3475f)
- depositor: Address
- amount: uint256"])
SwapRequestMsg(["SwapRequest
(msg 0x123456)
- ammPool: Address
- minAmountOut: uint256"])
end

Vault["Vault
(Asset Container)"]

subgraph "Different Asset Implementations"
JettonVault["Jetton Vault
(Different Implementation)"]
TONVault["TON Vault
(Different Implementation)"]
ExtraCurrencyVault["Extra-Currency Vault
(Different Implementation)"]
end

subgraph "DEX Component"
AMMPool["AMM Pool"]
end

subgraph "User"
Trader["Trader"]
end

JettonVault -->|implements| Vault
TONVault -->|implements| Vault
ExtraCurrencyVault -->|implements| Vault

Vault --> PayoutRequest
Vault --> DepositRequest
Vault --> SwapRequestMsg

Trader -->|"sends SwapRequest"| Vault
Vault -->|"forwards to"| AMMPool

VaultAbstraction["Asset Abstraction Layer"]
Vault --- VaultAbstraction

VaultNote["Any contract that implements
the Vault interface can serve
as a Vault regardless of asset type.
Each asset has its own implementation."]
VaultAbstraction --- VaultNote

AMMPoolNote["AMM Pool only knows Vault addresses,
not the actual asset details,
enabling uniform asset handling"]
AMMPool --- AMMPoolNote

TraderNote["Trader interacts with assets
only through their Vaults"]
Trader --- TraderNote

style Vault fill:#f9f,stroke:#333,stroke-width:2px
style VaultAbstraction fill:#eef,stroke:#888,stroke-dasharray: 5 5
style VaultNote fill:#fff,stroke:#888,stroke-dasharray: 5 5
style AMMPoolNote fill:#fff,stroke:#888,stroke-dasharray: 5 5
style TraderNote fill:#fff,stroke:#888,stroke-dasharray: 5 5
style JettonVault fill:#dfd,stroke:#333
style TONVault fill:#dfd,stroke:#333
style ExtraCurrencyVault fill:#dfd,stroke:#333
style AMMPool fill:#ddf,stroke:#333
style Trader fill:#ffe,stroke:#333
```

### Swap Process

```mermaid
graph LR
%% Horizontal flow from left to right
subgraph Step1["Step 1: Trader Sends Swap Request to Vault"]
Trader1["Trader"]
VaultA1["Vault A
(e.g. TON Vault)"]

Trader1 -->|"Swap Request
(msg 0x123456)
ammPool: Address
minAmountOut: uint256"| VaultA1
end

subgraph Step2["Step 2: Vault A Forwards to AMM Pool"]
VaultA2["Vault A
(e.g. TON Vault)"]
AMMPool1["AMM Pool Contract"]

VaultA2 -->|"Swap In
Send tokens to pool"| AMMPool1
end

subgraph Step3["Step 3: AMM Pool Calculates and Requests Output"]
AMMPool2["AMM Pool Contract"]
VaultB1["Vault B
(e.g. Jetton Vault)"]

AMMPool2 -->|"Swap Out
Request token transfer"| VaultB1
end

subgraph Step4["Step 4: Vault B Pays Out to Trader"]
VaultB2["Vault B
(e.g. Jetton Vault)"]
Trader2["Trader"]

VaultB2 -->|"PayoutFromPool
(msg 0x74f7a60)
amount: uint256
receiver: Address"| Trader2
end

%% Connect the steps in sequence
Step1 --> Step2
Step2 --> Step3
Step3 --> Step4

%% Notes
AMM_FormulaNotes["Constant Product Formula
x * y = k
Where x and y are token balances"]
AMMPool1 --- AMM_FormulaNotes

VaultAbstractionNote["Asset Abstraction Layer:
AMM Pool doesn't know asset implementation details"]
AMMPool2 --- VaultAbstractionNote

TraderNote["Swap request exact format
depends on exact Vault type"]
Trader1 --- TraderNote

style Trader1 fill:#ffe,stroke:#333,stroke-width:2px
style Trader2 fill:#ffe,stroke:#333,stroke-width:2px
style VaultA1 fill:#dfd,stroke:#333,stroke-width:2px
style VaultA2 fill:#dfd,stroke:#333,stroke-width:2px
style VaultB1 fill:#dfd,stroke:#333,stroke-width:2px
style VaultB2 fill:#dfd,stroke:#333,stroke-width:2px
style AMMPool1 fill:#f9f,stroke:#333,stroke-width:2px
style AMMPool2 fill:#f9f,stroke:#333,stroke-width:2px

style AMM_FormulaNotes fill:#fff,stroke:#888,stroke-dasharray: 5 5
style VaultAbstractionNote fill:#fff,stroke:#888,stroke-dasharray: 5 5
style TraderNote fill:#fff,stroke:#888,stroke-dasharray: 5 5

style Step1 fill:none,stroke:#333,stroke-width:1px
style Step2 fill:none,stroke:#333,stroke-width:1px
style Step3 fill:none,stroke:#333,stroke-width:1px
style Step4 fill:none,stroke:#333,stroke-width:1px
```

### Liquidity Provision Process

```mermaid
graph LR
%% Horizontal flow from left to right
subgraph StepA["Step 1: Deposit Assets"]
Depositor1["Depositor (Wallet)"]
VaultA1["Vault A
(TON Vault)"]
VaultB1["Vault B
(Jetton Vault)"]

Depositor1 -->|"Asset A Deposit"| VaultA1
Depositor1 -->|"Asset B Deposit"| VaultB1
end

subgraph StepB["Step 2: Vaults Notify LP Deposit Contract"]
VaultA2["Vault A
(TON Vault)"]
VaultB2["Vault B
(Jetton Vault)"]
LPDeposit1["LP Deposit Contract"]

VaultA2 -->|"PartHasBeenDeposited
(msg 0xe7a3475f)
depositor: Address
amount: uint256"| LPDeposit1
VaultB2 -->|"PartHasBeenDeposited
(msg 0xe7a3475f)
depositor: Address
amount: uint256"| LPDeposit1
end

subgraph StepC["Step 3: LP Deposit Confirms to AMM Pool"]
LPDeposit2["LP Deposit Contract"]
AMMPool1["AMM Pool Contract"]

LPDeposit2 -->|"BothPartHasBeenDeposited
(msg 0x333333)
depositor: Address
amountA: uint256
amountB: uint256"| AMMPool1
end

subgraph StepD["Step 4: AMM Pool Returns Extra Coins"]
AMMPool2["AMM Pool Contract"]
VaultB3["Vault
(Some vault, depending on how price changed)"]
Depositor2["Depositor (Wallet)"]

AMMPool2 -->|"PayoutFromPool
(due to slippage)"| VaultB3

VaultB3 -->|"Return extra coins"| Depositor2
end

subgraph StepE["Step 5: AMM Pool Mints LP Tokens"]
AMMPool3["AMM Pool Contract"]
Depositor3["Depositor (Wallet)"]

AMMPool3 -->|"Mint LP Tokens"| Depositor3
end

%% Connect the steps in sequence
StepA --> StepB
StepB --> StepC
StepC --> StepD
StepD --> StepE

%% Notes
VaultANote["Different implementation
for TON assets"]
VaultA1 --- VaultANote

VaultBNote["Different implementation
for Jetton assets"]
VaultB1 --- VaultBNote

LPDepositNote["Coordinates deposits
Ensures atomicity
Destroys itself after deposit
Acts like a point of synchronization"]
LPDeposit1 --- LPDepositNote

AMMPoolNote["Never interacts directly
with underlying assets"]
AMMPool1 --- AMMPoolNote

style Depositor1 fill:#ffe,stroke:#333,stroke-width:2px
style Depositor2 fill:#ffe,stroke:#333,stroke-width:2px
style Depositor3 fill:#ffe,stroke:#333,stroke-width:2px
style VaultA1 fill:#dfd,stroke:#333,stroke-width:2px
style VaultA2 fill:#dfd,stroke:#333,stroke-width:2px
style VaultB1 fill:#dfd,stroke:#333,stroke-width:2px
style VaultB2 fill:#dfd,stroke:#333,stroke-width:2px
style VaultB3 fill:#dfd,stroke:#333,stroke-width:2px
style LPDeposit1 fill:#fdd,stroke:#333,stroke-width:2px
style LPDeposit2 fill:#fdd,stroke:#333,stroke-width:2px
style AMMPool1 fill:#f9f,stroke:#333,stroke-width:2px
style AMMPool2 fill:#f9f,stroke:#333,stroke-width:2px
style AMMPool3 fill:#f9f,stroke:#333,stroke-width:2px

style VaultANote fill:#fff,stroke:#888,stroke-dasharray: 5 5
style VaultBNote fill:#fff,stroke:#888,stroke-dasharray: 5 5
style LPDepositNote fill:#fff,stroke:#888,stroke-dasharray: 5 5
style AMMPoolNote fill:#fff,stroke:#888,stroke-dasharray: 5 5

style StepA fill:none,stroke:#333,stroke-width:1px
style StepB fill:none,stroke:#333,stroke-width:1px
style StepC fill:none,stroke:#333,stroke-width:1px
style StepD fill:none,stroke:#333,stroke-width:1px
style StepE fill:none,stroke:#333,stroke-width:1px
```

## Key Features

- **Tact based**: Easy to read and understand code, with a focus on safety and security
- **Asset Abstraction**: Vault is a contract, that stores any kind of an Asset (TON, Jetton, Extra Currency, etc.). All other contracts stores Vaults addresses.
- **Cheap Cross-pool swaps**: This architecture allows to easily perform cross-pool swaps with very low network fees.
- **AMM (Automated Market Maker)**: Using constant product formula for exchange rate determination
- **Atomic Liquidity Addition**: Synchronized asset addition through the LP Deposit contract
- **Exchange Fee**: 0.3% fee on token exchanges (configurable)
- **Constrained Swap Requests**: Ability to specify minimum output token amount and timeout

## Project Setup and Development

To start working with T-Dex, install all dependencies:

```shell
yarn install
```

Build the contracts:

```shell
yarn build
```

Other useful commands:

Run tests:

```shell
yarn test
```

Lint the code:

```shell
yarn lint
```

Format the code:

```shell
yarn fmt
```

## Testing

The project uses Jest for testing. Tests are located in the `sources/tests` directory and cover various aspects of the T-Dex functionality:

- `amm-pool.spec.ts` - Tests for the AMM Pool functionality
- `liquidity-deposit.spec.ts` - Tests for liquidity deposit process
- `liquidity-payloads.spec.ts` - Tests for payload handling in liquidity operations
- `swap-payloads.spec.ts` - Tests for payload handling in swap operations

To run all tests:

```shell
yarn test
```

## Contract Configuration

If you need to modify the contract configuration, update the [`tact.config.json`](./tact.config.json) file. For a description of `tact.config.json`, see the [Configuration page in the Tact documentation](https://docs.tact-lang.org/book/config).

## License

[MIT](./LICENSE)