Введение в смарт-контракты TON
Смарт-контракты — это сердце любого децентрализованного приложения на TON. Однако контракты TON принципиально отличаются от контрактов Ethereum: здесь каждый контракт — независимый актор со своим балансом, кодом и состоянием. Понимание жизненного цикла контракта (деплой, сообщения, заморозка, удаление) критически важно, потому что в TON контракт может быть удалён, если закончились средства на оплату хранения.
В модулях M01 и M02 мы изучили архитектуру TON и работу TVM. Теперь переходим к практике — написанию смарт-контрактов. Этот модуль посвящён языку Tact — высокоуровневому языку для разработки на TON.
Контракт как актор
В M02 мы разобрали модель акторов: каждый контракт в TON — это независимый актор со своим состоянием, кодом и балансом. Повторим ключевые свойства:
- Изолированное состояние — контракт не имеет доступа к данным других контрактов
- Общение через сообщения — единственный способ взаимодействия между контрактами
- Асинхронная обработка — каждое сообщение обрабатывается в отдельной транзакции
- Оплата хранения — контракт платит за хранение своего состояния (storage fees)
Жизненный цикл смарт-контракта
Смарт-контракт в TON проходит через несколько этапов:
1. Деплой (Deployment)
Контракт создаётся путём отправки специального внешнего сообщения (external message), содержащего:
- Код контракта — TVM bytecode
- Начальные данные — initial state (данные при создании)
Адрес контракта вычисляется до деплоя как хеш от кода и начальных данных:
address = hash(initial_code + initial_data)
Это означает, что адрес детерминирован — зная код и начальные данные, можно вычислить адрес контракта ещё до его создания.
Детерминистические адреса позволяют отправлять TON на адрес контракта до его деплоя. Контракту нужен баланс для оплаты хранения, поэтому сначала пополняют адрес, а затем деплоят.
2. Получение сообщений
После деплоя контракт ожидает входящие сообщения. TON различает два типа:
- Internal messages — от других контрактов или кошельков внутри блокчейна
- External messages — от внешнего мира (например, от кошелька пользователя)
3. Обработка и изменение состояния
При получении сообщения TVM:
- Загружает код и состояние контракта
- Выполняет код обработки сообщения
- Обновляет состояние контракта
- Формирует исходящие сообщения (если есть)
4. Отправка сообщений
Контракт может отправить ноль или более исходящих сообщений в результате обработки. Это основной механизм взаимодействия между контрактами.
5. Заморозка и удаление
Если баланс контракта падает ниже порога, он замораживается (frozen) — перестаёт обрабатывать сообщения. Замороженный контракт можно восстановить, пополнив баланс. Если баланс остаётся нулевым длительное время, контракт удаляется.
TON vs Ethereum: ключевые отличия
| Свойство | TON | Ethereum |
|---|---|---|
| Модель исполнения | Асинхронная (акторы) | Синхронная (EVM) |
| Доступ к чужому состоянию | Невозможен | Возможен (SLOAD при CALL) |
| Атомарность | Каждое сообщение — отдельная транзакция | Вся цепочка вызовов атомарна |
| Адрес контракта | hash(code + data) — детерминистический | Зависит от nonce отправителя |
| Хранение | Оплата за время хранения (storage fees) | Однократная запись (SSTORE) |
| Reentrancy | Невозможна по архитектуре | Главная уязвимость |
Асинхронность vs синхронность
В Ethereum вызов A.call(B) происходит синхронно: A ждёт результата от B в той же транзакции. В TON контракт A отправляет сообщение контракту B и продолжает работу. Ответ от B придёт в отдельной транзакции через несколько секунд. Это требует другого подхода к проектированию: вместо синхронных вызовов — обмен сообщениями с обработкой ответов.
Bounced-сообщения
Когда контракт не может обработать входящее сообщение (ошибка, недостаточно газа), TON отправляет сообщение обратно отправителю — это bounced message (отскочившее сообщение).
Bounce — важнейший механизм безопасности в TON:
- Если вы отправили TON на контракт, который не может их принять, средства вернутся
- Разработчик обязан обрабатывать bounced-сообщения, чтобы корректно восстановить состояние
Мы подробно разберём bounce-механизм в уроке 05 этого модуля.
Языки для написания контрактов
В экосистеме TON существуют три языка для разработки смарт-контрактов:
| Язык | Уровень | Назначение |
|---|---|---|
| Tact | Высокоуровневый | Основной язык для новых проектов |
| Tolk | Среднего уровня | Замена FunC с улучшенным синтаксисом |
| FunC | Среднего уровня | Legacy-язык (чтение существующих контрактов) |
В этом модуле мы используем Tact — самый доступный и продуктивный язык для разработки на TON.
Частые ошибки
- Забывают пополнить адрес контракта перед деплоем, и без начального баланса контракт не сможет оплатить хранение и будет немедленно заморожен.
- Не обрабатывают сценарий заморозки контракта: если баланс упадёт ниже порога, контракт перестанет отвечать на сообщения.
- Предполагают, что адрес контракта случаен, хотя в TON адрес детерминирован (hash от кода и данных) и может быть вычислен до деплоя.
- Переносят архитектуру Ethereum-приложения «один-в-один» в TON, игнорируя асинхронность и отсутствие атомарных кросс-контрактных вызовов.
Проверка знанийПочему адрес смарт-контракта в TON можно узнать до его деплоя?
Проверьте понимание
Закончили урок?
Отметьте его как пройденный, чтобы отслеживать свой прогресс
Войдите чтобы оценить урок