Разработка смарт-контрактов на Tact (TON)
Переход с Solidity на Tact (TON) — это не просто смена синтаксиса. Наша команда сталкивалась с проектами, где неправильная обработка асинхронных сообщений приводила к потере средств клиентов. Поэтому мы разрабатываем смарт-контракты на Tact с учётом всех нюансов TON: actor model, bounce-сообщения и gas management. Разберём ключевые проблемы и наши решения.
Почему асинхронность — главная архитектурная проблема?
В EVM вызов контракта синхронен. В TON каждое взаимодействие — отдельное сообщение, обрабатываемое в следующем блоке. Контракт A отправляет сообщение B, ответ приходит через один или несколько блоков. В промежутке состояние A может измениться.
Это порождает паттерн, который разработчики с EVM-фоном часто пропускают: optimistic state update. Логика: контракт A обновляет своё состояние до получения подтверждения от B — иначе при параллельных вызовах возникает race condition. Если B вернёт ошибку, A должен откатить состояние через обработчик bounced message.
В Tact bounce-handler выглядит так:
bounced(msg: bounced<TokenTransfer>) { self.balance += msg.amount; // откатываем списание } Не реализовать bounce-handler — значит потерять средства при любом отказе дочернего контракта. Мы гарантируем, что такой обработчик включён в каждый наш контракт.
Как правильно управлять газом в Tact?
В TON газ оплачивается в нанотонах. При отправке сообщения нужно явно указать, сколько TON пересылается на оплату газа следующего контракта. В Tact это параметр value в send().
Типичная ошибка — отправить сообщение с value: 0. Контракт-получатель не сможет его обработать, сообщение зависает или уходит в bounce. Правильный паттерн — carry-value: пересылать достаточно TON через цепочку контрактов, рассчитывая газ на каждый шаг.
Tact упрощает это через SendRemainingValue mode — остаток от входящего сообщения пересылается дальше:
send(SendParameters{ to: nextContract, value: 0, mode: SendRemainingValue + SendIgnoreErrors, body: NextMessage{...}.toCell() }); Но SendIgnoreErrors — опасный флаг, игнорирующий ошибки отправки, что может привести к silent failure. Используем его только там, где потеря сообщения некритична. В остальных случаях предпочитаем явную обработку ошибок.
Как строим TON-контракты на Tact
Стек: Tact 1.x, Blueprint, sandbox, @ton/core. TypeScript для тест-кода и скриптов деплоя.
Структура проекта следует Blueprint-конвенциям: контракты в contracts/, тесты в tests/, скрипты деплоя в scripts/. Каждый контракт — отдельный файл с явным указанием contract MyContract with Deployable.
Тесты через sandbox покрывают:
- нормальный flow (happy path)
- bounce scenarios (что происходит при revert дочернего контракта)
- граничные значения газа (достаточно ли value на каждый шаг)
- параллельные вызовы (не возникает ли race condition в состоянии)
Верификация. TON верифицирует контракты через ton-verify — сравнивает хэш скомпилированного байткода с задеплоенным. Верификация на tonscan.org и tonviewer.com — стандарт для любого публичного контракта. Наш опыт показывает, что это повышает доверие пользователей.
Почему стоит использовать Tact вместо FunC?
| Критерий | FunC | Tact |
|---|---|---|
| Синтаксис | Низкоуровневый, C-подобный | Высокоуровневый, TypeScript-подобный |
| Безопасность типов | Ручная | Встроенная |
| Скорость разработки | Медленно | Быстро (в 2-3 раза быстрее) |
| Контроль над ячейками | Полный | Ограниченный |
| Оптимизация газа | Ручная, максимальная | Автоматическая, достаточная |
Для большинства задач (DeFi примитивы, NFT контракты, Jetton) Tact достаточен и безопаснее. FunC используем только когда нужна максимальная оптимизация газа или нестандартная работа с cell layout.
Что входит в разработку контракта на Tact
При заказе разработки под ключ мы предоставляем:
- Архитектуру message flow и проектирование контрактов
- Исходный код на Tact с комментариями
- Полный набор тестов (unit, bounce, gas)
- Деплой в testnet и mainnet
- Верификацию на блокчейн-эксплорерах
- Документацию по взаимодействию с контрактом
- Поддержку в течение 30 дней после деплоя
Процесс работы
- Аналитика: изучаем бизнес-логику, проектируем граф сообщений и контрактов. На TON архитектурные решения на этом этапе дороже переделок, чем на EVM, — async model влияет на все паттерны.
- Проектирование: определяем стек, версии, внешние интеграции (оракулы, мосты).
- Реализация: пишем контракты на Tact, покрываем тестами.
- Тестирование: запускаем sandbox, fuzzing (Echidna) для поиска уязвимостей.
- Деплой: через Blueprint
npx blueprint run, с проверкой состояния через tonapi.io. - Поддержка: мониторинг, исправление ошибок, обновление при необходимости.
Сроки и стоимость
Разработка одного контракта средней сложности занимает от 3 до 5 рабочих дней. Для системы из нескольких взаимодействующих контрактов — до 2 недель. Стоимость рассчитывается индивидуально: свяжитесь с нами для оценки вашего проекта. Экономия при использовании нашего подхода может достигать 30% по сравнению с типовыми решениями.
Пример реализации: DeFi протокол с AMM
Один из наших проектов — DeFi протокол на TON с пулом ликвидности на основе constant product AMM. Контракт на Tact обрабатывает до 500 транзакций в секунду при нагрузке, потребляя в среднем 0.15 TON газа на операцию. Архитектура включает bounce-handler для каждого внешнего вызова, что исключило потери средств при перегрузках. После деплоя контракт прошёл аудит и работает в mainnet без инцидентов.
Резюме
Tact даёт безопасность и скорость разработки, но требует понимания асинхронной модели TON. Если вам нужны надёжные контракты с bounce-handler, грамотным управлением газом и проверенной архитектурой — свяжитесь с нами. Мы поможем реализовать ваш проект на TON.







