Разработка смарт-контрактов на 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.
Разработка смарт-контрактов
Мы столкнулись с ситуацией: контракт задеплоен, через две недели приходит сообщение — пул дренирован на $800k. Смотрим транзакцию в Tenderly: атакующий вызвал deposit(), внутри callback на ERC-777 повторно вызвал withdraw() — баланс обновился только после второго выхода. Классическая reentrancy, но не через ETH transfer, а через хук ERC-777. ReentrancyGuard стоял только на withdraw().
Такие случаи — не редкость. Смарт-контракт — это финансовая логика без возможности пропатчить её ночью. Наша команда разрабатывает контракты под ключ, встраивая защиту от reentrancy, MEV и gas-атак на ранних этапах.
Как мы разрабатываем смарт-контракты под ключ
Начинаем с аудита бизнес-логики и выбора стека. Solidity 0.8.x — стандарт для EVM-совместимых чейнов: Ethereum, Arbitrum, Optimism, Polygon, BSC, Avalanche C-Chain. Для Solana используем Rust и Anchor: модель аккаунтов и программ требует явного объявления всех ресурсов. Для проектов с формальной верификацией подходит Move (Aptos, Sui) — линейные типы языка исключают копирование ресурсов на уровне компилятора. Vyper выбираем для контрактов, где критична простота аудита (Curve Finance).
| Язык |
Модель исполнения |
Типичная область |
Риски |
| Solidity 0.8.x |
EVM, последовательное исполнение |
DeFi, NFT, токены |
Reentrancy, переполнение (unchecked) |
| Rust (Anchor) |
Solana, параллельное |
Высоконагруженные DEX, игры |
Неправильное объявление аккаунтов |
| Move |
Aptos/Sui, ресурсная |
Крупные протоколы |
Сложность экосистемы |
| Vyper |
EVM, ограниченный синтаксис |
Критические контракты (Curve) |
Зависимость от стабильности компилятора |
Gas optimization — не преждевременная оптимизация, а архитектурное решение. На Ethereum mainnet деплой плохо спроектированного контракта может стоить 2–5 ETH только из-за неоптимального storage layout. Переупаковка структуры Proposal с 7 слотов до 4 сэкономила 18k gas на каждом голосовании — около $1.5 при gas price 30 gwei. Экономия на масштабе протокола с тысячами голосований в день даёт ощутимую годовую выгоду.
Типичные ошибки в gas: передача массивов через memory вместо calldata в external функциях (дороже в 2–3 раза); использование require с длинными строками вместо custom error error InsufficientBalance(...). Кастомные ошибки дешевле на 50–200 gas на revert и передают структурированные данные фронтенду.
Почему аудит смарт-контрактов критичен для безопасности
Аудит — не разовая проверка, а встроенный этап разработки. Используем три уровня:
-
Статический анализ —
Slither (30 секунд в CI) выявляет reentrancy, неинициализированные переменные, опасный delegatecall.
-
Фаззинг и invariant тесты —
Foundry с --fuzz-runs 50000 находит edge cases, которые пропускают сотни unit-тестов. Реальный кейс: AMM контракт с кастомной математикой после 150 тестов в Hardhat — Foundry нашёл integer division truncation, позволявший пылевой атаке копить dust на контракте. Echidna проверяет инварианты («сумма всех балансов ≤ totalSupply»).
-
Ручной code review — наши инженеры с опытом 10+ лет в блокчейне выявляют логические ошибки, которые не ловят инструменты. Для протоколов с TVL > $1M обязателен внешний аудит со стороны Trail of Bits, Consensys Diligence или OpenZeppelin. Срок — 2–4 недели.
Любой апгрейдируемый протокол должен иметь timelock. TimelockController из OpenZeppelin: операция предлагается → ждёт минимальный delay (48–72 часа) → выполняется. Без timelock один скомпрометированный deployer wallet = потеря всего пула.
Какие паттерны апгрейда выбираем
| Паттерн |
Механизм |
Риск |
Когда использовать |
Наш опыт |
| Transparent Proxy (OZ) |
admin vs user разделение |
Storage collision, centralization |
Стандартные проекты |
15+ реализаций |
| UUPS |
Логика апгрейда в implementation |
Забыть _authorizeUpgrade → контракт навсегда сломан |
Газ-оптимизированные проекты |
7 проектов |
| Diamond (EIP-2535) |
Множество facets |
Сложность аудита |
Крупные протоколы с 10+ контрактами |
3 внедрения |
| Beacon Proxy |
Один beacon для множества proxies |
Beacon = single point of failure |
Фабрики однотипных контрактов |
5 фабрик |
Storage collision — главная опасность прокси. Implementation v2 не должен добавлять переменные перед существующими. OpenZeppelin Upgrades plugin для Hardhat и Foundry проверяет это автоматически, но только при использовании его API.
Как защитить контракт от MEV и front-running
На Ethereum mainnet транзакции в mempool видны всем. MEV-боты проводят sandwich-атаки на DEX, фронтраннинги минтинга и governance. Решение: commit-reveal scheme для аукционов, приватная отправка через Flashbots PROTECT RPC. EIP-7702 и PBS (proposer-builder separation) меняют картину, но пока не массово.
Процесс разработки
-
Аналитика — спецификация функций, диаграмма вызовов, анализ edge cases. Без этого кодинг начинается впустую.
-
Разработка — Solidity/Rust с тестами параллельно. Тест → код → рефакторинг. Используем Foundry для fuzz и invariant тестов.
-
Внутренний аудит — Slither + Echidna + ручной code review. Foundry invariant tests для протокольных инвариантов.
-
Внешний аудит — для проектов с реальными деньгами. Срок: 2–4 недели.
-
Деплой — Foundry scripts или Hardhat Ignition с verify на Etherscan. Gnosis Safe для ownership transfer сразу после деплоя.
-
Мониторинг — Tenderly alerts, OpenZeppelin Defender, Forta Network.
Что входит в работу
- Документация на архитектуру и спецификацию контракта (NatSpec).
- Исходный код с репозиторием и CI (Slither, Foundry, coverage).
- Развёрнутая версия контракта с verify на блокчейн-эксплорере.
- Результаты аудита (внутреннего и внешнего по запросу).
- Доступы к мониторингу и управлению (Gnosis Safe).
- Гарантия на код: фиксы критических багов в течение месяца после деплоя.
- Консультация по интеграции с веб-интерфейсом (wagmi, RainbowKit).
Сроки ориентировочно
- ERC-20 token с базовыми функциями: 1–2 недели
- Vesting контракт с cliff/linear schedule: 2–3 недели
- NFT ERC-721/1155 с маркетплейсом: 4–6 недель
- AMM или lending протокол: 2–4 месяца
- Мультичейн протокол с bridge: 4–7 месяцев
Аудит добавляет 3–6 недель и идёт параллельно с финальным тестированием где возможно. Стоимость рассчитывается индивидуально — свяжитесь с нами, и мы оценим ваш проект бесплатно.
Закажите разработку смарт-контракта — получите консультацию по архитектуре и защите от reentrancy, MEV и gas-атак. Хотите обсудить детали? Напишите нам — мы подберём оптимальный стек под вашу задачу.