Bounce / non-bounce сообщение
Флаг в сообщении TON, определяющий поведение при ошибке. Bounceable возвращает TON отправителю, если получатель не принял; non-bounceable отправляет безвозвратно.
Синонимы: bounceable, non-bounceable, баунс сообщение, отскок
Bounce-флаг — это бит в заголовке сообщения TON, определяющий, что произойдёт, если получающий контракт по какой-то причине не смог обработать сообщение. Это критически важная особенность TON, не имеющая прямого аналога в Ethereum.
Два режима
- Bounceable (bounce = true). Если получающий контракт упал с ошибкой или его не существует, сообщение возвращается отправителю — TON-сумма приходит обратно (минус потраченный газ). Это режим по умолчанию для сообщений между смарт-контрактами.
- Non-bounceable (bounce = false). Сообщение уходит «безвозвратно». Если получатель не принял — TON остаются на его адресе (даже если контракт там не развёрнут). Используется для развёртывания новых контрактов и для отправки на свежие, ещё не активные адреса.
Зачем это нужно
В Ethereum любой transfer — синхронный: либо прошёл, либо ревертнул всю транзакцию. В TON всё асинхронно — отправитель не знает, дойдёт ли сообщение до получателя в следующем блоке. Bounce-механизм решает эту проблему:
- Если jetton wallet получателя сломан — TON и jetton-ы вернутся обратно, не потеряются.
- Если контракт случайно отправил на несуществующий адрес — деньги не уйдут в пустоту.
- Если контракт упал из-за ошибки в коде — отправитель получит уведомление и сможет повторить.
В адресе тоже есть bounce-флаг
Сам адрес TON в base64-форме содержит этот флаг:
EQ...— bounceable. Кошельки и большинство контрактов используют этот вариант. Если адрес контракт «не понял» — деньги вернутся.UQ...— non-bounceable. Используется для отправки на новые адреса, на которых ещё нет развёрнутого контракта.
Когда вы копируете адрес с биржи или из кошелька, формат подбирается автоматически. Но при ручной отправке стоит проверять: если адрес ещё не активирован (no contract on chain), отправка в bounceable-режиме приведёт к возврату средств с потерей газа.
Практический пример
Сценарий: вы только что создали кошелёк, поделились адресом, и кто-то отправляет вам 100 TON.
- Если адрес был передан в bounceable-форме (
EQ...), а ваш кошелёк ещё не развёрнут — TON уйдут отправителю обратно с минусом ~0,01 TON газа. Раздражает. - Если адрес в non-bounceable-форме (
UQ...) — TON останутся на адресе, и вы их получите при первом своём действии, развернув кошелёк через первое исходящее сообщение.
Поэтому новые кошельки рекомендуют делиться адресом в UQ-форме, пока не сделана первая исходящая транзакция.
Технически
Bounce-сообщения автоматически формируются TVM при ошибке исполнения. У такого сообщения есть стандартный префикс — первые 32 бита payload равны 0xFFFFFFFF. Получатель (изначальный отправитель) может проверить этот префикс в своём коде и обработать ошибку: записать в логи, попробовать снова, уведомить пользователя.
В стандартном wallet-контракте bounce-сообщения тихо принимаются и отображаются в истории как «возврат». В кастомных контрактах разработчику нужно явно прописать обработку bounce, иначе ошибки будут теряться.