Ошибка: Exit code 40 — Contract stopped

Причина и решение ошибки exit code 40 (cannot process message / контракт не принял сообщение) в TON.

Exit code 40 — Contract stopped

Action phase не смог обработать исходящее сообщение: не хватило средств на доставку, сообщение слишком большое или Merkle depth превышен. В эксплорерах и логах это часто выглядит как «contract stopped» / «cannot process message».


Причина

  • после compute phase на балансе осталось меньше, чем нужно, чтобы фактически отправить out-msg;
  • тело/stateInit сообщения раздуты — не влезают в лимиты после rewriting;
  • слишком глубокое Merkle-дерево в payload;
  • SendMode оставляет нулевой баланс, а fees ещё не оплачены.

Официальная формулировка TVM: Cannot process a message — not enough funds, the message is too large, or its Merkle depth is too big.


Решение

tact (fallback highlight)
// Tact 1.6+
receive("withdraw") {
    // Не опустошай контракт до нуля в том же сообщении, где шлёшь out-msg
    let leave = ton("0.05");
    require(myBalance() > leave, "Reserve for fees");

    send(SendParameters {
        to: sender(),
        value: myBalance() - leave,
        mode: SendPayGasSeparately,
        bounce: true,
        body: "withdraw".asComment(), // короткое body — без гигантских ref-деревьев
    });
}
typescript
// @ton/core ^0.59 — проверяй размер cell до отправки
import { beginCell } from "@ton/core";

const body = beginCell().storeStringTail("ok").endCell();
if (body.bits.length > 1023) {
  throw new Error("Body too large for a single cell — split into refs");
}

Как избежать в будущем

Резервируй TON на fees, держи out-messages компактными, избегай глубоких цепочек storeRef. В sandbox смотри transactions[].description.actionPhase.resultCode === 40 и сверяй баланс после compute.

Материалы gramdocs.tech носят образовательный характер и не являются финансовой, юридической или инвестиционной рекомендацией. Работа с блокчейном TON и токеном Gram связана с рисками потери средств. Правовая информация