Разработка DEX на TON
TON — это не EVM-совместимый чейн. Это означает, что весь накопленный опыт с Solidity, Hardhat, OpenZeppelin придётся отложить. Контракты на TON пишутся на FunC или более новом Tact, архитектура storage принципиально другая, и паттерны DeFi, которые работают на Ethereum, здесь требуют переосмысления. Команды, которые приходят с EVM-фоном и недооценивают эту разницу, обычно переписывают контракты дважды.
Асинхронная модель TON — главное отличие
На Ethereum вызов swap() на роутере — это синхронная цепочка: роутер вызывает пул, пул обновляет резервы, возвращает результат. Всё в одной транзакции.
На TON каждый вызов между контрактами — отдельное сообщение. Роутер отправляет internal message в пул, пул обрабатывает его в отдельной транзакции, отправляет ответное сообщение роутеру. Это две транзакции, разнесённые во времени. Атомарности в EVM-смысле нет.
Для DEX это означает:
- Своп не атомарен: между отправкой входящих токенов и получением выходящих проходит несколько секунд
- Reentrancy в EVM-смысле невозможна, но race conditions между сообщениями реальны
- Откат всей цепочки при ошибке требует явной обработки: bounce-сообщения для возврата токенов
Bounce messages — обязательный паттерн
Если пул не может выполнить своп (например, slippage превышен), он должен отправить bounce-сообщение с возвратом токенов. Если контракт не обрабатывает bounced messages — токены теряются навсегда.
() on_bounce(slice in_msg_body) impure {
int op = in_msg_body~load_uint(32);
if (op == op::transfer_notification) {
;; Получили bounce при transfer — возвращаем токены отправителю
send_tokens(original_sender, amount, jetton_wallet_addr);
}
}
Архитектура DEX на TON: AMM через Jetton
TON не имеет native ERC-20. Вместо него — Jetton standard (TEP-74): каждый пользователь имеет отдельный jetton wallet контракт. Для свопа пользователь отправляет transfer на свой jetton wallet с payload, который содержит данные свопа. Jetton wallet отправляет transfer_notification в пул.
Архитектура пула для AMM:
User Jetton Wallet A
→ transfer(amount, pool_address, forward_payload=swap_data)
→ Pool Jetton Wallet A (transfer_notification)
→ Pool Contract (swap message)
→ Pool Jetton Wallet B (transfer)
→ User Jetton Wallet B
Пять контрактов, пять транзакций на один своп. Это нормально для TON, но требует аккуратного fee management: каждый шаг потребляет TON на gas. Пользователь должен приложить достаточно TON (обычно 0.1–0.3 TON) для оплаты всей цепочки.
Ключевые протоколы как референс
Ston.fi — первый крупный AMM на TON, работает с 2022. Стандартная x*y=k формула, но с адаптацией под асинхронную модель. Код открыт и является де-факто референсной реализацией для TON DEX.
DeDust — использует собственный Vault архитектуру: центральный Vault контракт для каждого пула вместо jetton wallet подхода. Более газо-эффективно, но менее совместимо со стандартным Jetton flow.
Tonswap — работает через TON DNS и Telegram-интеграцию, ориентирован на Telegram Mini Apps.
Concentrated Liquidity на TON: инженерная задача
Реализация Uniswap V3-style concentrated liquidity на TON — значительно сложнее, чем на EVM. Причина: операции с tick-массивом требуют итерации, которая в TON ограничена вычислительными лимитами на транзакцию (gas на TON называется compute fee и ограничен).
На EVM Uniswap V3 использует bitmap для быстрого поиска ближайшего инициализированного tick. На TON аналог — hashtable в storage, но каждый доступ к ячейке стоит дороже из-за структуры Cell-based storage.
Практическое решение для MVP: упрощённая версия concentrated liquidity с ограниченным числом диапазонов (до 20-50 на пул) — достаточно для большинства use cases, без экстремальной оптимизации tick traversal.
Разработка на FunC vs Tact
FunC — низкоуровневый язык, напоминает C. Полный контроль над stack и cell операциями. Обязателен для понимания, как TON хранит данные.
Tact — высокоуровневый язык с типизацией, struct-ами и более читаемым синтаксисом. Компилируется в FunC. Для новых проектов рекомендуем Tact — меньше ошибок с cell/slice парсингом.
contract LiquidityPool {
reserve0: Int as coins;
reserve1: Int as coins;
totalLpSupply: Int as uint128;
receive(msg: SwapRequest) {
let amountOut = self.calculateAmountOut(msg.tokenIn, msg.amountIn);
require(amountOut >= msg.minAmountOut, "Slippage exceeded");
self.updateReserves(msg.tokenIn, msg.amountIn, amountOut);
// Отправляем output tokens пользователю
self.sendTokens(msg.recipient, amountOut, msg.tokenOut);
}
}
Тестирование и инструменты
Blueprint — официальный фреймворк для разработки и тестирования TON контрактов (аналог Hardhat для TON). Поддерживает sandbox для локального тестирования без реальной ноды.
Sandbox (из @ton/sandbox) — in-process TON VM для unit тестов. Критично для тестирования bounce message handling и многошаговых транзакционных цепочек.
import { Blockchain } from '@ton/sandbox'
import { LiquidityPool } from '../build/LiquidityPool'
const blockchain = await Blockchain.create()
const pool = blockchain.openContract(await LiquidityPool.fromInit(token0, token1))
const swapResult = await pool.sendSwap(user.getSender(), {
tokenIn: token0Address,
amountIn: toNano('100'),
minAmountOut: toNano('95')
})
expect(swapResult.transactions).toHaveTransaction({
to: pool.address,
success: true
})
Интеграция с Telegram Mini Apps
TON DEX практически всегда интегрирован с Telegram через TON Connect протокол. Пользователи подключают Tonkeeper, MyTonWallet или Telegram Wallet. Интерфейс строится как Telegram Mini App с @tonconnect/ui-react библиотекой.
Особенность: в Telegram Mini App нет window.ethereum. Весь web3-стек специфичен для TON: @ton/ton для RPC, @ton/core для типов, TON Connect для wallet подключения.
Процесс работы
Аналитика (2–3 дня). Определяем тип AMM (x*y=k, stable swap, concentrated), список пулов для запуска, экономическую модель fee.
Проектирование контрактов (3–5 дней). Схема сообщений между контрактами, bounce handling, fee accumulation, LP token (Jetton).
Разработка (4–8 недель). Pool контракт, Router, LP Jetton minter, тесты в Blueprint sandbox.
Фронтенд и TON Connect (2–3 недели). Swap UI, liquidity management, аналитика.
Деплой и тестнет. Testnet (TON testnet) → mainnet. TON имеет отдельную testnet с faucet для TON и тестовых Jettonов.
Ориентиры по срокам
Базовый AMM x*y=k с одним пулом и minimal UI — 6–8 недель. Полноценный DEX с роутером для мультихопов, аналитикой, Telegram Mini App — 3–4 месяца. Concentrated liquidity с менеджментом позиций — добавляет ещё 4–6 недель.







