Learning Platform
Глоссарий Troubleshooting
Урок 04.03 · 18 мин
Продвинутый
BounceError HandlingRecoveryCompensation

Bounce Handling и Error Recovery

Проблема: ошибки в async chains

В синхронных системах ошибка = exception → try/catch → rollback. В TON каждый шаг — отдельная транзакция. Если шаг 3 из 5 упал — шаги 1 и 2 уже выполнены и необратимы.

Проблема:
Step 1: [OK] User → DEX: отправил 100 USDT     (необратимо)
Step 2: [OK] DEX: рассчитал курс                (необратимо)
Step 3: [NO] DEX → User: отправка TON — FAIL    (контракт не существует?)
                                                
Результат: User потерял 100 USDT, TON не получил

Bounce Messages: автоматический safety net

Когда контракт получает internal message с bounce: true и не может его обработать (бросил exception), TON автоматически создаёт bounce message:

Bounce Message Flow
Contract A
msg (bounce: true)
Contract B FAIL
Contract A
bounce msg
A: handle bounce → refund

Что содержит bounce message

Bounce message:
- bounced: true (флаг — это bounce, не обычное сообщение)
- src: адрес Contract B (откуда bounced)
- value: остаток value после вычета gas
- body: первые 256 бит оригинального body (для идентификации)

Bounce Handler Pattern

Каждый контракт, отправляющий critical messages, должен иметь bounce handler:

// Паттерн bounce handler
recv_internal(msg) {
  // Проверяем: это bounce message?
  if (msg.bounced) {
    // Прочитать op из bounced body
    int op = msg.body.read_uint(32);
    int query_id = msg.body.read_uint(64);
    
    // Компенсация в зависимости от операции
    if (op == op::internal_transfer) {
      // Transfer не удался — вернуть баланс
      self.balance += msg.original_amount;
      // Уведомить пользователя
      emit_log("transfer_failed", query_id);
    }
    return;
  }
  
  // Нормальная обработка сообщений...
}
WARNING

Ограничения bounce

  1. Bounce body содержит только первые 256 бит оригинального сообщения — может быть недостаточно для идентификации
  2. Bounce message тоже стоит gas — если value недостаточно, bounce не отправится
  3. External messages не bounceются — нет адреса возврата
  4. Bounce не каскадный — если bounce handler тоже бросит исключение, второго bounce не будет

Error Recovery Strategies

Strategy 1: Compensation (Saga)

При ошибке — выполнить обратное действие:

Transfer failed (bounce):
  → Вернуть баланс отправителю
  → Обновить pending state

Strategy 2: Retry with state

Сохранить pending операцию и повторить:

Retry pattern:
  → Сохранить pending_operation в state
  → При bounce — increment retry_count
  → Если retry_count < MAX_RETRIES — повторить с увеличенным gas
  → Если retry_count >= MAX_RETRIES — compensation

Strategy 3: Admin intervention

Для критических ситуаций — pause + admin recovery:

Emergency pattern:
  → Обнаружена критическая ошибка
  → Контракт переходит в PAUSED state
  → Только admin может вызвать recovery function
  → Admin анализирует ситуацию и вызывает refund/resume

Design Checklist для Error Handling

ПроверкаОписаниеКритичность
Все internal messages с bounce:true?Если нет — средства теряются при ошибкеCritical
Bounce handler реализован?Обработка bounce для каждого типа сообщенияCritical
Gas достаточно для bounce?Value > compute + forward + bounce gasHigh
Timeout для pending операций?Что если ответ никогда не придёт?High
Admin recovery для critical paths?Паузa + ручное восстановление при catastrophic failureHigh
Проверка знанийKnowledge check
ОтветAnswer

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 2. Contract A отправляет 1 TON в Contract B с bounce:true. Contract B бросает исключение. Сколько TON получит Contract A обратно в bounce?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5