> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ton.org/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.ton.org/feedback

```json
{
  "path": "/contract-dev/debug",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Debugging smart contracts

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

<Aside>
  All examples from this article are available on [GitHub](https://github.com/ton-org/docs-examples/tree/main/guidebook/debug).
</Aside>

Errors in smart contracts can produce an [exit code](/tvm/exit-codes), often indicating a bug in the contract. Use debugging methods to locate and fix the issue.

## Log to the console

Most commonly used to print common values: transactions and get-method results.

* Use `findTransaction()` to find a transaction by its properties.
* Use `flattenTransaction()` to inspect transactions in a more human-readable format.

```ts TypeScript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
import '@ton/test-utils';
import { toNano } from '@ton/core';
import { Blockchain } from '@ton/sandbox';
import { Test } from './output/sample_Test';
import { findTransaction } from '@ton/test-utils';
import { flattenTransaction } from '@ton/test-utils';

const setup = async () => {
    const blockchain = await Blockchain.create();
    const owner = await blockchain.treasury('deployer');
    const contract = blockchain.openContract(
        await Test.fromInit(),
    );
    const deployResult = await contract.send(
        owner.getSender(),
        { value: toNano(0.5), bounce: true },
        null,
    );
    return { blockchain, owner, contract, deployResult };
};

it('should deploy correctly', async () => {
    const { contract, deployResult } = await setup();

    const txToInspect = findTransaction(
        deployResult.transactions,
        {
            to: contract.address,
            deploy: true,
        },
    );
    if (txToInspect === undefined) {
        throw new Error('Requested tx was not found.');
    }
    // User-friendly output
    console.log(flattenTransaction(txToInspect));
    // Verbose output
    console.log(txToInspect);
});
```

## Dump values from a contract

There are three TVM debug [instructions](/tvm/instructions#fe-debug): `DUMPSTK`, `STRDUMP`, and `DUMP`.

These instructions are wrapped in functions with different names in each language:

* Tolk: Functions on a global `debug` object.
* FunC: Global functions from `stdlib.fc`.
* Tact: `dumpStack` for `DUMPSTK` and the [dump function](https://docs.tact-lang.org/ref/core-debug/#dump) for the other two. Tact also prints the exact line where `dump` is called, so it can quickly be found in the code.

<Aside type="caution">
  Debug instructions consume gas and affect gas measurement. Remove them before measuring gas or deploying to production.
</Aside>

## Explore TVM logs

```ts TypeScript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
const blockchain = await Blockchain.create();
blockchain.verbosity.vmLogs = "vm_logs";
```

Of all [verbosity levels](/contract-dev/testing/reference#verbosity-2), the two are the most useful:

* `vm_logs` — outputs VM logs for each transaction; includes executed instructions and occurred exceptions.
* `vm_logs_full` — outputs full VM logs for each transaction; includes executed instructions with binary offsets, the current stack for each instruction, and gas used by each instruction.

Typical output for `vm_logs` looks like this:

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
...
execute SWAP
execute PUSHCONT x30
execute IFJMP
execute LDU 64
handling exception code 9: cell underflow
default exception handler, terminating vm with exit code 9
```

The contract attempts to load a 64-bit integer from the slice using `LDU 64`. Since there is not enough data, execution stops with [exit code 9](/tvm/exit-codes#9%3A-cell-underflow).

Inspect the same code with the `vm_logs_full` verbosity level. The output is heavily truncated at the top.

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
...
execute PUSHCONT x30
gas remaining: 999018
stack: [ 500000000 CS{Cell{02b168008d0d4580cd8f09522be7c0390a7a632bda4a99291c435b767c95367ebe78e9af0023d36bc5f97853f4c898f868f95b035ae8f555a321d0ffce8d9f6165e2252d7a9077359400060e9fc800000000003d0902d1b85b3919} bits: 711..711; refs: 2..2} 0 Cont{vmc_std} ]
code cell hash: F9EAC82B7999AEEF696D592FE2469B9069FB05ED35C92213D7EE516F45AB97CA offset: 344
execute IFJMP
gas remaining: 999000
stack: [ 500000000 CS{Cell{02b168008d0d4580cd8f09522be7c0390a7a632bda4a99291c435b767c95367ebe78e9af0023d36bc5f97853f4c898f868f95b035ae8f555a321d0ffce8d9f6165e2252d7a9077359400060e9fc800000000003d0902d1b85b3919} bits: 711..725; refs: 2..2} ]
code cell hash: F9EAC82B7999AEEF696D592FE2469B9069FB05ED35C92213D7EE516F45AB97CA offset: 352
execute LDU 64
handling exception code 9: cell underflow
default exception handler, terminating vm with exit code 9
```

<Aside type="tip">
  To investigate the error in more detail, examine the TVM source code for the `LDU` instruction.
  Sometimes several instructions are implemented within a single `exec_*` method. For example, [LDU](/tvm/instructions#d3-ldu) (`load_uint`), [LDI](/tvm/instructions#d2-ldi) (`load_int`) and it's preload versions (`preload_uint`and`preload_int`).

  Check how `LDU` [is implemented](https://github.com/ton-blockchain/ton/blob/34823b1ea378edbe3bc59f3bcc48126480a0b768/crypto/vm/cellops.cpp#L981).
</Aside>

Stack is printed as `[bottom, ..., top]`, where `top` is the top of the stack.

Here, the stack contains two values:

* **Top:** the slice from which data is being read — `CS{Cell{...} bits: 711..725; refs: 2..2}`
* **Bottom:** an integer value — `500000000`

However, the slice contains only `725` bits, of which `711` bits and both [references](/foundations/serialization/cells) have already been read. The contract attempted to read `64` more bits, but the slice did not contain enough remaining data.

In FunC, locate the `load_uint(64)` call causing the issue and ensure enough bits are available or adjust the read width.

### TVM log limits

The size of TVM debug output depends on the verbosity level:

| Level | Setting                                                                        | Max size              |
| ----- | :----------------------------------------------------------------------------- | :-------------------- |
| 0     | `none`                                                                         | 256 bytes *(default)* |
| 1–4   | `vm_logs` <br /> `vm_logs_location` <br /> `vm_logs_gas` <br /> `vm_logs_full` | 1 MB                  |
| 5     | `vm_logs_verbose`                                                              | 32 MB                 |

When the output exceeds its limit, it is truncated **from the bottom** — older entries are discarded, and only the most recent lines are kept. Logs are **not rotated**.

## Explore the trace

For traces that are not too large, print all transactions and inspect them.

```ts TypeScript theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
const result = await contract.send(
    owner.getSender(),
    { value: toNano(0.5), bounce: true },
    null,
);
for (const tx of result.transactions) {
    console.log(flattenTransaction(tx));
}
```

For large traces, use a GUI tool. Two tools are commonly used:

* [TonDevWallet trace view](https://github.com/TonDevWallet/TonDevWallet) — requires the TonDevWallet application; does not require a custom `@ton/sandbox`; requires the `@tondevwallet/traces` package.
* [TxTracer Sandbox](/tvm/tools/txtracer) — requires a custom `@ton/sandbox` package; runs in the browser.

Also, these tools allow to explore logs of each transaction.

## Inspect BoC returned by APIs

When interacting with the blockchain using APIs, responses may include serialized cells in [BoC (bag of cells)](/foundations/serialization/boc), TON's standard cell serialization format.

In API responses, BoC is typically represented as a base64-encoded string, which is not human-readable. Example API response:

```json theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
{
  "stack": [
    {
      "type": "cell",
      "value": "te6cckEBAQEAFwAAKSioyuboQNrK5ubCzspA0txAxsrY2Whv0fw="
    }
  ]
}
```

The `"value"` field contains a base64-encoded BoC string representing a serialized cell. To decode and inspect its structure, use [`ton-cell-abi-viewer`](https://ton-cell-abi-viewer.vercel.app/). After decoding:

```json theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
{
  "success": true,
  "value": {
    "kind": "Message",
    "len": 20,
    "text": "Test message in cell"
  }
}
```

### How to use

1. Copy the base64 BoC string or hex, if applicable, from the API response.
2. Paste it into the [`ton-cell-abi-viewer`](https://ton-cell-abi-viewer.vercel.app/).
3. Provide the TL-B schema for the cell, if available.
4. Inspect the decoded structure.

<Aside type="note">
  Without an explicit TL-B schema, the tool attempts to recognize common cell patterns automatically. Since BoC represents raw binary data, some cells may not be fully recognizable or may be parsed incorrectly.
</Aside>

Use this tool when API responses contain serialized cells that require structural inspection during debugging.

## Debug with TVM Retracer

Even when a contract executes successfully (exit code = `0`) with no errors, the actions may not produce the expected on-chain result. [TVM Retracer](/tvm/tools/retracer) replays the transaction and displays VM-level execution in detail.

### Scenarios for retracing

* All [execution phases](/foundations/phases) complete without errors, yet the expected outcome is missing.
* An action is skipped, or a transfer does not reach its destination.
* A step-by-step view of how the TVM executes contract logic is required, i.e. to trace a bug in a high-level smart-contract language compiler.

### How to analyze a transaction

1. Obtain the transaction hash from a [blockchain explorer](/ecosystem/explorers/overview).
2. Open [TVM Retracer](/tvm/tools/retracer) and enter the transaction hash.
3. Review the execution:
   * Inspect **Logs section** for executed instructions and exceptions.
   * Examine **Actions cell (C5)** to review data passed between contracts.
   * Check **message modes** — some modes can suppress errors, causing actions to be skipped.
