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)
- Host: GitHub
- URL: https://github.com/tact-lang/dex
- Owner: tact-lang
- License: mit
- Created: 2025-02-04T20:52:03.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-06-18T09:29:27.000Z (about 1 year ago)
- Last Synced: 2025-06-18T10:29:16.393Z (about 1 year ago)
- Topics: decentralized-exchange, dex, tact, tact-lang, ton
- Language: TypeScript
- Homepage:
- Size: 595 KB
- Stars: 9
- Watchers: 3
- Forks: 0
- Open Issues: 21
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# OpenDeFi Library: Decentralized Exchange in Tact, T-Dex

**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)